You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router严格模式导致SocketIO事件触发两次

React Strict Mode导致Socket事件重复触发的原因及解决方案

原因分析

React的StrictMode(严格模式)在开发环境下会特意重复执行部分操作,用来帮你排查代码里的潜在问题,包括:

  • 组件的构造、渲染逻辑
  • useEffect的回调函数
  • useEffect的清理函数

你的代码里,StrictMode会让TablesView组件的useEffect先执行一次(绑定room_made等事件),紧接着触发清理函数,然后再重新执行一次useEffect(再次绑定room_made事件)。但你的清理函数里没移除room_made的事件监听,导致同一个事件被绑定了两次回调。服务器发一次room_made事件,客户端就会触发两次回调,最终让games数组重复添加元素。

注意:这个重复执行的行为只在开发环境存在,生产环境下StrictMode不会做这个操作,但你的代码本身存在未正确清理副作用的问题,必须修复。

解决方案

在useEffect的清理函数中,补上对room_made事件的移除监听即可:

function TablesView() {
  const [games, setGames] = useState([]);
  // ...其他状态

  useEffect(() => {
    socket.on("room_made", function (msg) {
      var gameID = msg["gameID"];
      var chairs = msg["chairs"];
      setGames((oldGames) => [...oldGames, { gameID, chairs }]);
    });

    socket.on("disconnect", () => {
      setIsConnected(false);
    });

    return () => {
      socket.off("room_made"); // 新增:移除room_made事件监听
      socket.off("connect");
      socket.off("disconnect");
      socket.off("pong");
    };
  }, []);

  // ...组件渲染逻辑
}

这样,当StrictMode第一次执行清理函数时,会移除room_made的监听,第二次执行useEffect时重新绑定,就不会出现重复监听的问题了,同时也避免了组件卸载时的内存泄漏风险。

额外优化建议

如果你的socket实例是全局共享的,建议使用命名函数作为事件回调,而不是匿名函数,这样socket.off可以精准移除指定的回调,不会影响其他组件对同一个事件的监听:

function TablesView() {
  const [games, setGames] = useState([]);
  // ...其他状态

  // 定义命名回调函数
  const handleRoomMade = (msg) => {
    var gameID = msg["gameID"];
    var chairs = msg["chairs"];
    setGames((oldGames) => [...oldGames, { gameID, chairs }]);
  };

  useEffect(() => {
    socket.on("room_made", handleRoomMade);

    socket.on("disconnect", () => {
      setIsConnected(false);
    });

    return () => {
      socket.off("room_made", handleRoomMade); // 精准移除指定回调
      socket.off("connect");
      socket.off("disconnect");
      socket.off("pong");
    };
  }, []);

  // ...组件渲染逻辑
}

内容的提问来源于stack exchange,提问作者Sam Gates

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:39:32