使用 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);
  }, []);
  ...
}