useState Set 方法没有更新变量值

问题描述 投票:0回答:1

我正在尝试使用“async-mqtt”库,以便在 Next.js 应用程序上使用 MQTT 协议。 我按预期检索 MQTT 消息,当我记录它们时,我可以在本地终端(而不是在浏览器中)看到它们。

基本上我只是尝试简单地使用我创建的 useState 的

setData
方法。 我尝试在 mqtt
message
事件中使用它,但我在 UI 上看不到任何变化。 我不明白为什么
setData
在 MQTT 事件中不起作用,但当然可以通过创建的测试按钮起作用。 当然,我还缺少一些东西。

我还尝试将

useEffect
data
一起用作依赖项数组中的依赖项,但没有被调用,当然,除非我从按钮手动设置数据。

我尝试寻找类似的问题,但似乎都不适合我的情况。

这是我当前的代码:

"use client"
import React, { useEffect, useState } from 'react';

const MQTTSubscriber = () =\> {
const\[data, setData\] = useState()

    const MQTT = require("async-mqtt");
    const client = MQTT.connect("tcp://broker.hivemq.com");
    
    const doStuff = async () => {
      console.log("Starting");
      try {
        //await client.publish("my topic", "It works!");
        await client.subscribe("my topic")
        console.log("Hello world")
        // This line doesn't run until the server responds to the publish
        //await client.end();
        // This line doesn't run until the client has disconnected without error
        console.log("Done");
      } catch (e){
        // Do something about it!
        console.log(e.stack);
        process.exit();
    }

}

client.on("message", (topic, message) => {
 const payload = { topic, message: message.toString() };
 console.log(message.toString());
 setData(message.toString()) //Here the issue, nothing happens.
});

client.on("connect", doStuff);

return (
 <div>
   <button onClick={() => setData("Test")}\> Set data manually test </button>
   <p>{"Data: " + data}</p>
 </div>
);
};

export default MQTTSubscriber;

我向您展示我的 package.json 文件:

{
  "name": "next-webgl-unity-mqtt",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "async-mqtt": "^2.6.3",
    "autoprefixer": "10.4.16",
    "bufferutil": "^4.0.7",
    "eslint": "8.49.0",
    "eslint-config-next": "13.5.2",
    "mqtt": "^5.0.5",
    "next": "13.5.2",
    "postcss": "8.4.30",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "tailwindcss": "3.3.3",
    "utf-8-validate": "^5.0.10"
  }
}

我希望使用 React useState 显示从 mqtt 接收到的数据。

你知道为什么会发生这种情况吗?或者最终你知道一些解决方法吗?

如果您需要更多信息,请随时询问我!

提前谢谢你

编辑:Hamude Shahin 给出的答案似乎是正确的步骤,但是这样做我现在在客户端面临另一个错误,错误如下

WebSocket connection to 'ws://broker.hivemq.com/' failed

next.js react-hooks mqtt next.js13 mqtt.js
1个回答
0
投票

您面临的问题可能与状态更改时 React 如何重新渲染组件有关。在您的代码中,您在 MQTT 消息事件处理程序中使用 setData 来更新数据状态。但是,当 React 自己的事件处理之外(例如在 MQTT 事件处理程序中)发生状态更改时,React 可能不会触发组件的重新渲染。

为了确保数据状态的更改触发组件的重新渲染,您可以使用 useEffect 挂钩。您提到您尝试使用 useEffect,但它不起作用。让我们尝试解决这个问题。

以下是如何在数据状态更改时使用 useEffect 重新渲染组件:

'use client'
import React, { useEffect, useState } from 'react';

const MQTTSubscriber = () => {
  const [data, setData] = useState('');

  const MQTT = require('async-mqtt');
  const client = MQTT.connect('tcp://broker.hivemq.com');

  const doStuff = async () => {
    console.log('Starting');
    try {
      await client.subscribe('my topic');
      console.log('Hello world');
      console.log('Done');
    } catch (e) {
      console.log(e.stack);
      process.exit();
    }
  };

  useEffect(() => {
    // This effect runs when 'data' state changes
    client.on('message', (topic, message) => {
      const payload = { topic, message: message.toString() };
      console.log(message.toString());
      setData(message.toString()); // This should trigger a re-render
    });

    client.on('connect', doStuff);

    return () => {
      // Clean up the MQTT client when the component unmounts
      client.end();
    };
  }, []); // The empty dependency array means this effect runs once after initial render

  return (
    <div>
      <button onClick={() => setData('Test')}>Set data manually test</button>
      <p>{'Data: ' + data}</p>
    </div>
  );
};

export default MQTTSubscriber;

更新

基于您的更新。检查这个问题

© www.soinside.com 2019 - 2024. All rights reserved.