首页 > 解决方案 > socket.io 监听器在功能性 React 中触发太多次

问题描述

我正在使用 create-react-app、react hooks 构建一个在线棋盘游戏,并且正在使用 sockets.io 在连接的用户之间传输数据(玩家位置、活动玩家等)。逻辑流程是用户做出选择,该选择被添加到状态数组中,然后通过套接字将更新的状态推送给所有连接的用户。问题是负责从后端接收套接字数据并更新每个连接用户的用户数据的 useEffect 侦听器触发了太多次而不是一次。

代码:

向后端发送调用:

try {
          console.log(currentCard, typeof(currentCard.title), tech)
          setUser1Data({
            ...user1Data,
             userTech: [...user1Data.userTech, currentCard.title]
          });
        } finally {
          console.log(user1Data)
            socket.emit("p1state", user1Data);
           pass();
        }

后端接收器/发射器:

socket.on("p1state", function(state) {
    console.log(state)
    io.emit("p1state", state)
  })

客户端监听器:

  useEffect(() => {
    socket.on("p1state", state => {
      console.log("1")
      setUser1Data({...user1Data, state});
    });
  }, [user1Data]);

我注意到一些“有趣”的事情:这个 useEffect 被触发了太多次。第一次触发时,它会按照应有的方式设置所有内容,但随后每次都会覆盖先前的设置,恢复为原始的 user1Data 状态对象。

此外,在后端,当客户端连接时,我有一个 console.log 触发。即使我目前仅使用一个浏览器选项卡在本地进行测试,它仍在记录多个用户连接的事件。

标签: javascriptreactjssocketsreact-hooks

解决方案


当前useEffect正在使用依赖数组中的状态,并在更新函数中设置相同的状态。如您所见,这会导致无限循环。

useEffect(() => {
    socket.on("p1state", state => {
      console.log("1")
      setUser1Data(userData => ({...userData, state}));
    });
}, []);

相反,您可以使用状态设置器的函数版本,以便它为您提供准确的prevState而不是依赖于闭包中的状态表示。


推荐阅读