我正在尝试使用“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
您面临的问题可能与状态更改时 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;
基于您的更新。检查这个问题。