javascript - 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 触发。即使我目前仅使用一个浏览器选项卡在本地进行测试,它仍在记录多个用户连接的事件。
解决方案
当前useEffect
正在使用依赖数组中的状态,并在更新函数中设置相同的状态。如您所见,这会导致无限循环。
useEffect(() => {
socket.on("p1state", state => {
console.log("1")
setUser1Data(userData => ({...userData, state}));
});
}, []);
相反,您可以使用状态设置器的函数版本,以便它为您提供准确的prevState
而不是依赖于闭包中的状态表示。
推荐阅读
- json - 无法将有效负载 (JSON) 从 Team Foundation Server (TFS) 传递到 AWS Lambda 函数
- javascript - Javascript 树结构到数组的转换
- c# - 使用 `Entity Framework` 绑定`CSHTML` 中的动态字段
- node.js - 链接nodeJs包时出错
- django - 如何在 django 2 模板中查询主键对象
- sql - 如何将值插入 SQL 表的另一列,其中第一列使用执行 xp_cmdshell 获取值?
- django - django - 通过循环遍历所有字段并分配值来创建模型的实例
- string - 如何在bash中连接字符串?
- java - Java中的字符串数组 - 声明固定长度,将值传递给构造函数并添加到它们
- java - 为什么当 Object 为 null 时会导致 NullPointerException?