我正试图在React中使用钩子处理一个对象列表。对象的更新是用MQTT接收的。
我首先尝试使用一个名为 mqtt-react-hooks (最近该库的源头已经从Github上消失了)。这个库提供了一个 useSubscription
函数,其中包括返回最新收到的订阅主题的消息。
基本上我的组件是这样的,我的对象是节点。
function MQTTApp(props) {
const [nodes, setNodes] = useState([]);
const { lastMessageOnTopic } = useSubscription('node/#');
...
}
这种方法的问题是,我的组件被渲染成... 每次收到消息. 当收到一个MQTT消息时,需要对其进行解析,并对其进行处理。不一定 到节点的更新。我想要的是我的组件是 只会 当 节点表.
所以我试着甩掉 mqtt-react-hooks 库,并编写我自己的代码。下面还使用了 MQTT.js. 它是基于 本文.
我的代码现在看起来是这样的。
function MQTTApp(props) {
const [nodes, setNodes] = useState([]);
function handleMessage(m) {
...
setNodes([...nodes, newNode]);
}
useEffect(() => {
const client = mqttService.getClient();
mqttService.onMessage(client, handleMessage);
mqttService.subscribe(client, 'node/#');
return () => mqttService.closeConnection(client);
}, []);
...
}
我的想法是,这个组件创建一个MQTT客户端,并订阅话题 安装时. 我在这里的问题是,回调了 始终引用初始节点列表 (它是空的)。由于我将我的节点列表视为 不变 我总是 复制 当我打电话 setNodes
因此 nodes
参考资料. 所以到最后,当收到更新时,我一直在丢失以前的节点。
我想不出一个干净简单的方法来处理这个问题。有人有什么办法吗?
有谁有办法吗?
你的 useEffect
被执行一次。该 nodes
在 handleMessage
的函数引用,它被附加到 onMessage
监听器总是使用节点的初始值(因为闭包)。
所以使用回调方式来设置状态。
function MQTTApp(props) {
const [nodes, setNodes] = useState([]);
function handleMessage(m) {
...
setNodes(prev => [...prev, newNode]); <-------- see here
}
useEffect(() => {
const client = mqttService.getClient();
mqttService.onMessage(client, handleMessage);
mqttService.subscribe(client, 'node/#');
return () => mqttService.closeConnection(client);
}, []);
...
}