socket.io 监听器在功能性 React 中触发太多次

Posted

技术标签:

【中文标题】socket.io 监听器在功能性 React 中触发太多次【英文标题】:socket.io listener firing too many times in functional React 【发布时间】:2020-06-24 17:58:23 【问题描述】:

我正在使用 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。尽管我目前仅使用一个浏览器选项卡在本地进行测试,但它仍在记录多个用户连接事件。

【问题讨论】:

你必须清理效果:useEffect(()=>do stuff; return ()=>clean up stuff。为什么user1Data会发生变化,它来自哪里,是否需要改变(可能使用useMemo)? 【参考方案1】:

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

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

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

【讨论】:

您的代码有效,谢谢!只是为了确保我理解它,传播 userData 的 userData 函数,userData 是已经保存在状态中的内容的占位符名称? (所以我们可以很容易地将其命名为“香蕉”以获得相同的结果?) 是的,状态设置器有一个功能版本,它接收上一个状态(当然是设置器)作为第一个参数,你可以随意命名【参考方案2】:

我遇到了类似的问题。我解决了它,使 useEffect 每次卸载时都关闭套接字(并在每次安装/更新后打开/重新打开。这是我的代码:

    useEffect(()=>
        const socket = io("http://localhost:3000")
        socket.on(userId, (arg) => 
            //stuff
        ); 
        return () => socket.emit('end'); //close socket on unmount
    ) 

【讨论】:

以上是关于socket.io 监听器在功能性 React 中触发太多次的主要内容,如果未能解决你的问题,请参考以下文章

服务器的 socket.io 监听器无故触发两次

React Native、NodeJS、Socket.io

socket.io useEffect 清理函数 react

Socket.io - React:如何在 React 中检索保存的 socket.io 数据(MongoDB)?

带有 socket.io 的单页应用程序中的特定于部分的侦听器

从 socket.io 中删除特定的类方法监听器