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

React中两组件共用WebSocket仅一个生效的问题排查

问题分析与解决:WebSocket多组件监听冲突

问题描述

服务器通过UDP接收流数据后,使用WebSocket广播给前端。前端两个React组件分别处理广播数据中的score和session字段,单独使用任一组件时功能正常,但同时挂载两个组件时,只有一个组件能正确接收并更新数据,另一个无响应;刷新页面后,生效的组件可能切换。

核心原因

  1. 前端回调覆盖:两个组件共用同一个WebSocket实例,且均通过赋值式设置onmessage回调(websocket.onmessage = function(){...})。这种方式会直接覆盖之前的回调函数,最终只有最后执行赋值操作的组件回调会生效,刷新页面后组件挂载顺序可能变化,导致生效组件切换。
  2. 服务器变量冲突:handle_session和handle_score的参数data与全局存储数据的data重名,会导致无法正确更新全局数据。

解决方案

1. 前端:改用事件监听实现多回调共存

使用addEventListener添加message事件监听,支持多个回调同时生效;同时在组件卸载时移除监听,避免内存泄漏。

修改后的Score.js:

function Score() {
  const [score, setScore] = useState(0);
  const websocket = useContext(SocketContext);

  const handleMessage = (e) => {
    const packet = JSON.parse(e.data);
    setScore(packet.score);
  };

  useEffect(() => {
    websocket.addEventListener('message', handleMessage);
    // 组件卸载时移除监听
    return () => {
      websocket.removeEventListener('message', handleMessage);
    };
  }, [websocket]);

  return <h6>{score}</h6>;
}

export default Score;

修改后的Session.js:

function Session() {
  const [session, setSession] = useState(0);
  const websocket = useContext(SocketContext);

  const handleMessage = (e) => {
    const packet = JSON.parse(e.data);
    setSession(packet.session);
  };

  useEffect(() => {
    websocket.addEventListener('message', handleMessage);
    // 组件卸载时移除监听
    return () => {
      websocket.removeEventListener('message', handleMessage);
    };
  }, [websocket]);

  return <h6>{session}</h6>;
}

export default Session;

2. 服务器端:修复变量名冲突与数据发送格式

将处理函数的参数名与全局data区分开,同时确保发送的是标准JSON字符串,避免前端解析出错:

// 全局存储数据
var data = {"score" : 0, "session" : 0};

// 监听UDP数据包
client.on(PACKETS.session, handle_session);
client.on(PACKETS.score, handle_score);

// 更新session字段
function handle_session(newData) {
    data['session'] = newData.session;
    websocket.broadcast(data);
}

// 更新score字段
function handle_score(newData) {
    data['score'] = newData.score;
    websocket.broadcast(data);
}

// 广播函数
websocket.broadcast = function broadcast(data) {
  websocket.clients.forEach(function each(client) {
    console.log(data);
    // 转换为JSON字符串发送
    client.send(JSON.stringify(data));
  });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:50:18