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

socket.on回调触发两次问题求助(socket.io 4.5.1版本)

为什么socket.on回调会触发两次?

核心原因:React StrictMode的重复执行机制

在React开发环境中,StrictMode会重复执行useEffect、useState初始化等钩子,目的是帮你提前检测潜在的bug。你的useEffect虽然设置了空依赖数组,但在StrictMode下会被执行两次,导致socket.on('recv_broadcast')被绑定了两次回调。当服务端推送消息时,两个回调都会触发,所以你会看到两次打印和状态更新。

另外,你的socket实例是在组件外部创建的,会被所有组件复用,但如果组件被多次挂载(比如路由切换后重新渲染),也可能导致重复绑定,但最常见的还是StrictMode的影响。

解决方案:添加清理函数解绑事件

在useEffect中添加返回函数,每次组件卸载(或StrictMode重复执行前)解绑对应的事件回调,确保始终只有一个回调被绑定:

修改客户端的useEffect代码:

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

const socket = io('ws://localhost:3001');

const Main = () => {
  const [message, setMessage] = useState<string>('');
  const [chat, setChat] = useState<string[]>([]);

  useEffect(() => {
    // 把回调抽成单独函数,方便精准解绑
    const handleRecvBroadcast = (message) => {
      console.log(message);
      setChat(state => [...state, message]);
    };

    socket.on('recv_broadcast', handleRecvBroadcast);

    // 清理函数:组件卸载/重复执行前解绑事件
    return () => {
      socket.off('recv_broadcast', handleRecvBroadcast);
    };
  }, []);

  const send = () => {
    setChat(state => [...state, message]);
    socket.emit('send_broadcast', message);
  }
  // ...其他代码
}

额外检查点

  • 确认是否在其他组件(比如父组件、同级组件)中也绑定了recv_broadcast事件
  • 从你的服务端代码看,socket.broadcast.emit只会给当前客户端之外的其他连接推送消息,服务端逻辑不存在重复发送问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:09:19