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

如何在React中带认证参数重新连接Socket.IO服务器

解决Socket.IO连接在token更新时的重连问题

直接上解决方案,核心是把token加入useEffect依赖数组,同时在token变化时销毁旧连接、创建新连接,具体实现如下:

1. 改造SocketProvider组件

import { createContext, useContext, useEffect, useState } from 'react';
import { io } from 'socket.io-client';

const SocketContext = createContext(null);

export const SocketProvider = ({ token, children }) => {
  const [socket, setSocket] = useState(null);

  useEffect(() => {
    // 断开现有连接(如果存在)
    if (socket) {
      socket.disconnect();
      setSocket(null);
    }

    // 没有token时不发起连接
    if (!token) return;

    // 创建新连接,携带JWT token到auth参数
    const newSocket = io(process.env.REACT_APP_SOCKET_URL, {
      auth: {
        token: token // 对应后端socket.handshake.auth.token
      }
    });

    // 处理连接成功/失败的情况
    newSocket.on('connect', () => {
      console.log('Socket连接成功');
      setSocket(newSocket);
    });

    newSocket.on('connect_error', (err) => {
      console.error('Socket连接失败:', err);
      setSocket(null);
    });

    // 清理函数:组件卸载或依赖变化时断开连接
    return () => {
      newSocket.disconnect();
    };
  }, [token]); // 关键:把token作为依赖,token变化时重新执行effect

  return (
    <SocketContext.Provider value={socket}>
      {children}
    </SocketContext.Provider>
  );
};

// 自定义hook方便组件使用
export const useSocket = () => useContext(SocketContext);

2. 使用SocketProvider时传入token

在你的App根组件(或登录后的路由外层),把用户登录后获取的token传入Provider:

// 比如App.js
import { SocketProvider } from './SocketProvider';
import { useState } from 'react';

function App() {
  const [userToken, setUserToken] = useState(localStorage.getItem('token'));

  // 登录成功后更新userToken
  const handleLogin = (token) => {
    localStorage.setItem('token', token);
    setUserToken(token);
  };

  return (
    <SocketProvider token={userToken}>
      {/* 你的页面组件,比如登录页、聊天页 */}
      <LoginPage onLogin={handleLogin} />
      <ChatRoom />
    </SocketProvider>
  );
}

关键说明

  • 依赖数组加入token:当用户登录后userToken更新,useEffect会自动触发,销毁旧连接(如果之前失败的连接存在)并创建新的带token的连接。
  • 断开旧连接:每次创建新连接前先断开旧的,避免多个无效连接占用资源。
  • 连接状态处理:通过connect和connect_error事件更新socket状态,确保组件能拿到有效的连接实例。
  • 关于children变化:如果确实需要在children变化时重连,可以把children加入useEffect依赖,但通常children变化(比如路由切换)不需要重建socket连接,除非你的业务场景有特殊需求——不过要注意,直接把children加入依赖可能会因为React元素的引用变化导致频繁重连,这种情况建议用useMemo包裹children,或者只在必要的业务场景下触发重连。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 05:22:25