使用 React hooks 和 MQTT 处理对象列表
Handling a list of objects with React hooks and MQTT
我正在尝试使用挂钩处理 React 中的对象列表。使用 MQTT 接收对象的更新。
我首先尝试使用一个名为 mqtt-react-hooks 的库(该库最近从 Github 中消失了)。该库提供了一个 useSubscription
功能,其中 returns 接收到有关订阅主题的最新消息。
基本上我的组件是这样的,我的对象是节点:
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
被执行了一次。附加到 onMessage
侦听器的 handleMessage
函数引用中的 nodes
始终使用节点的初始值(因为关闭)。
所以使用回调方法来设置状态。
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);
}, []);
...
}
我正在尝试使用挂钩处理 React 中的对象列表。使用 MQTT 接收对象的更新。
我首先尝试使用一个名为 mqtt-react-hooks 的库(该库最近从 Github 中消失了)。该库提供了一个 useSubscription
功能,其中 returns 接收到有关订阅主题的最新消息。
基本上我的组件是这样的,我的对象是节点:
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
被执行了一次。附加到 onMessage
侦听器的 handleMessage
函数引用中的 nodes
始终使用节点的初始值(因为关闭)。
所以使用回调方法来设置状态。
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);
}, []);
...
}