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

React + Socket.io:重复连接消息(Socket ID不同)的原因与解决

React严格模式下Socket.io重复连接的问题解析

1. 为什么严格模式会导致重复连接?

React严格模式仅在开发环境生效,它会刻意重复执行部分操作来排查潜在问题,包括组件的构造函数、render方法、useState/useReducer初始化函数,以及不带稳定依赖数组的useEffect。

如果你的前端Socket.io连接逻辑写在useEffect里且未正确处理清理,严格模式会触发两次useEffect执行:第一次创建socket连接后,严格模式会立即调用清理函数(若存在),随后再次执行useEffect创建第二个独立连接。后端因此收到两个不同的连接请求,自然会打印两次带不同ID的"User connected"日志。

2. 不关闭严格模式的修复方案

方案一:给useEffect添加清理函数

在创建socket的useEffect中返回清理函数,确保第一次创建的socket被正确销毁,只保留第二次执行后的稳定连接:

import { useEffect } from 'react';
import io from 'socket.io-client';

function ChatComponent() {
  useEffect(() => {
    const socket = io('http://localhost:3001');
    
    // 这里添加socket事件监听等业务逻辑
    
    // 清理函数:组件卸载或useEffect重新执行时断开连接
    return () => {
      socket.disconnect();
    };
  }, []); // 空依赖数组确保仅在组件挂载时执行逻辑

  return <div>Chat Component</div>;
}

方案二:用Ref标记连接状态

通过Ref标记是否已建立有效连接,避免重复创建socket实例:

import { useEffect, useRef } from 'react';
import io from 'socket.io-client';

function ChatComponent() {
  const socketRef = useRef(null);
  const isConnectedRef = useRef(false);

  useEffect(() => {
    if (!isConnectedRef.current) {
      socketRef.current = io('http://localhost:3001');
      isConnectedRef.current = true;

      // 这里添加socket事件监听等业务逻辑

      return () => {
        socketRef.current?.disconnect();
        isConnectedRef.current = false;
      };
    }
  }, []);

  return <div>Chat Component</div>;
}

方案三:确保useEffect依赖数组稳定

如果useEffect依赖了外部变量,要保证这些变量的引用稳定,避免因依赖频繁变化导致useEffect重复触发:

// 错误示例:每次渲染都会新建config对象,触发useEffect重复执行
useEffect(() => {
  const socket = io('http://localhost:3001', { transports: ['websocket'] });
}, [{ transports: ['websocket'] }]);

// 正确示例:将配置放在组件外部,保证引用稳定
const socketConfig = { transports: ['websocket'] };
useEffect(() => {
  const socket = io('http://localhost:3001', socketConfig);
  return () => socket.disconnect();
}, []);

内容的提问来源于stack exchange,提问作者Arpit Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 04:48:21