【问题标题】:Receiving same message multiple times via web socket. The older messages are replaced after 3 or 4 new chat messages通过网络套接字多次接收相同的消息。旧消息在 3 或 4 条新聊天消息后被替换
【发布时间】:2021-06-11 19:00:00
【问题描述】:

我正在将 web sockets 集成到 React with Django in back-end。

我可以发送消息,并从后端接收新消息。

问题是在发送了 3 或 4 条消息后,前面的消息在前端被新消息取代,但在后端一切正常,实际上刷新后一切正常。

如何正确更新这种情况下的状态?

编辑:

我现在发现的主要问题是,当我发送一个聊天时,状态会多次更新,并且它的长度每次都在变化,并且屏幕抖动很大。

切片

name: 'chat',
initialState: {
        chatMessages: [],
}

reducers: {
        setChatMessages(state, action) {
            const chatmessages = action.payload;
            return {...state, chatMessages:chatmessages}; 
        },
}

聊天

const chatMessagesSelector = useSelector(selectChats);
const chatMessages = chatMessagesSelector?.chatMessages

    chatSocket.onmessage = (e) => {
    var data = JSON.parse(e.data)
    var message = {message: data.message, user: data.user,
                    timestamp: data.timestamp};  
    //console.log(message)
    let updatedMessages = [...chatMessages];
    updatedMessages.push(message);
    dispatch(setChatMessages(updatedMessages));
}

这是在updatedMessages 上方记录的chatMessages 对象。

Array(1)
0: {user: "testuser", message: "check!", timestamp: "2021-03-09T09:15:09.408717+01:00}
length: 1

【问题讨论】:

  • 每 3 或 4 条消息后,有时对于其他用户,它会替换所有其他消息并仅显示当前消息
  • yes..chatMessages 来自减速器。我会更新提到它的问题。

标签: reactjs redux websocket react-redux


【解决方案1】:

以下代码(方法 1*):

chatSocket.onmessage = (e) => {
    var data = JSON.parse(e.data)
    var message = {message: data.message, user: data.user, timestamp: data.timestamp};
    let updatedMessages = [...chatMessages];
    updatedMessages.push(message);
    dispatch(setChatMessages(updatedMessages));

从 redux 读取并创建新数组并推送新元素并调度 整个 数组。

取而代之的是,(方法 2),您只需发送新的 元素 以由 reducer 推送到 redux 存储:

chatSocket.onmessage = (e) => {
    var data = JSON.parse(e.data)
    var message = {message: data.message, user: data.user, timestamp: data.timestamp};   
    dispatch(setChatMessages(message));

现在(对于方法 2)您需要在减速器中进行此更改:

reducers: {
   setChatMessages(state, action) {
      return {...state, chatMessages: [...state.chatMessages, action.payload]};}
}

你也可以这样做:

reducers: {
   setChatMessages(state, action) {
      state.chatMessages.push(action.payload)
}

因为:

Redux Toolkit 允许我们在 reducer 中编写“变异”逻辑。它 实际上并没有改变状态,因为它使用了 Immer 库, 它检测到“草稿状态”的变化并产生一个全新的 基于这些更改的不可变状态

*如果您的组件中的 chatMessages 已过时或延迟,则方法 1 可能存在错误。

编辑:

真正的问题似乎是您的事件监听器被注册多次

要修复它,您应该将其移至useEffectcomponentDidMount

useEffect(() => {
  chatSocket.onmessage = (e) => {
    var data = JSON.parse(e.data)
    // ...
  }
  return function cleanup() {
    // de-register the socket event
  }
}, [])

【讨论】:

  • 嗨,感谢您的回复。我刚刚尝试过这个,但是现在,我发送的每条消息对两个用户都显示超过 4 或 5 次,并且当我更改减速器时,没有消息被加载。
  • 嗨 console.log 数据,从服务器也显示 3 次或更多次,但只保存在数据库中一次,在后端打印出 receive 显示只发一次消息。当我更换减速机时,我看不到旧消息。
  • 试试CodeSandbox,我演示了如何在切片中调度单个“元素”和“推送”。
  • 谢谢,我去看看。但是我现在发现的主要问题是,当我发送聊天时,状态会多次更新,并且每次都会更改长度并且屏幕会抖动很多。
  • 是的,完美..现在可以了!非常感谢...:)
【解决方案2】:

您需要将新消息与旧消息连接起来,但您正在替换它们:

setChatMessages(state, action) {
  const chatMessages = action.payload;
  return { ...state, chatMessages: state.chatmessages.concat(chatMessages)};
}

如果您在本地存储相同的消息然后从套接字发回,请小心并避免重复。

【讨论】:

  • 您好,感谢您的回复。我试过了,但即使我已经初始化了它,也会收到错误chatMessages is not defined
  • 发现一个错误并在代码中修复它。有效载荷中的chatMessages 变量被初始化为全小写(chatmessages
  • 我试过了,但它仍然不能正确更新它,因为现在聊天部分不止一次显示所有内容..就像重复..有没有办法避免它?
  • 正如我所说,如果您将相同的消息从套接字推回,则可能存在重复。您可以按时间戳或 id 过滤它们,例如
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-12
相关资源
最近更新 更多