【问题标题】:mqtt-react-hooks Subscriber stops working after one messagemqtt-react-hooks 订阅者在收到一条消息后停止工作
【发布时间】:2022-01-07 06:14:50
【问题描述】:

我有一个使用 mqtt-react-hooks 和 redux 的简单反应应用程序。每次订阅者收到新消息时,我都想更新我的 redux 存储。

订阅者.tsx

import React, { useEffect} from 'react';
import { useSubscription } from 'mqtt-react-hooks';
import { useAppDispatch } from '../features/item/hooks';
import { addItem } from '../features/item/item-slice';

const Subscriber = () => {
  const { message } = useSubscription('queue');
  const dispatch = useAppDispatch();
  
  useEffect(() => {
    if (message && message.message) {
      dispatch(addItem(JSON.parse(message.message)));
    } 
  }, [message]);

  
  return (
        <span>{message}</span>
  );
};

export default Subscriber

App.tsx

import React from 'react';
import './App.css';
import {useAppSelector} from './features/item/hooks'
import { Connector } from 'mqtt-react-hooks'
import Subscriber from './mqtt/Subscriber'

function App() {
  const items = useAppSelector((state) => state.item.items);

  return (
    <>
      <Connector brokerUrl="ws://localhost:9001"
      options={{keepalive: 10}}>
      <div className="item-holder">
        {Array.from(items, ([key, it]) => ({ key, it })).map( (kvp) => { return <div>{kvp.it} key={kvp.key}></div>})}
      </div>
      <Subscriber />
      </Connector>
    </>
  );
}

export default App;

如果我从订阅者中删除useEffect,消息就会被接收和更新。我可以发送任意数量的消息。但是,当我在useEffect 中调用dispatch(addItem(... 时,它会收到第一条消息,但会忽略所有以后的消息。我的蚊子经纪人说客户端已关闭连接。它从不尝试重新连接。

我对反应很陌生。我有一种感觉,我根本没有做这件事。我真正想要的是一个基于来自 mqtt 主题的消息来维护状态的 redux 存储。该应用程序具有允许用户将消息发布回 mqtt 代理并更改 redux 状态的按钮。

编辑

根据要求,这是 addItem 代码。

import {createSlice, PayloadAction} from '@reduxjs/toolkit'

interface ItemState {
    items: Item[],
}

const initialState: ItemState = {
    items: []
}

const orderSlice = createSlice({
    name: 'items',
    initialState,
    reducers: {
        addItem(state, action: PayloadAction<Item>) {
          state.items.push(action.payload);
          
          return state;
        }
    }
});

export const { addItem } = itemSlice.actions;
export default itemSlice.reducer;

而useAppDispatch来自./features/item/hooks

import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { RootState, AppDispatch } from './item-store'

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

但是,我要补充一点,我摆脱了这个并使用通常的 useDispatch 和 useSelector 而不是“useApp____”版本并得到了相同的结果。

我认为问题出在 mqtt-react-hooks 钩子上,但我的 react-fu 技能还不够高,无法解决。

【问题讨论】:

  • 你能分享addItem的代码和你的reducer代码吗?
  • 请同时分享提供dispatch功能的useAppDispatch。尝试包含我们跟踪上述代码并查看/理解所有调用所需的所有相关代码。

标签: react-redux react-hooks mqtt redux-toolkit


【解决方案1】:

似乎发生了一系列事情,导致Connector 重新呈现并断开连接,这是我认为正在发生的事情:

  1. App 正在订阅存储状态,导致每次收到新消息时都会重新呈现。
  2. 每次 App 呈现时,您都在重新创建您的 mqtt 配置对象,因为您正在传递一个对象文字 {keepalive: 10}
  3. Connector.tsx 第 48 行,mqttConnect 回调取决于 mqtt 选项对象。 React 进行引用相等检查,查看选项已更改,并导致重新创建回调。
  4. Connector.tsx 第 59 行中,这会导致 useEffect 重新运行,因为回调发生了变化,这会调用它的 teardown 函数,从而结束 mqtt 连接。

要修复它,您应该在 App 之外创建 MQTT 选项,这样它们就不会改变。

【讨论】:

  • 这是正确答案!谢谢!我记住了修复参照平等问题的选项,现在它可以完美运行了! const options = useMemo(() =&gt; {return {keepalive: 10};}, []); 然后&lt;Connector brokerUrl="ws://localhost:9001" options={options}&gt;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-10
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多