React中两组件共用WebSocket仅一个生效的问题排查
问题分析与解决:WebSocket多组件监听冲突
问题描述
服务器通过UDP接收流数据后,使用WebSocket广播给前端。前端两个React组件分别处理广播数据中的score和session字段,单独使用任一组件时功能正常,但同时挂载两个组件时,只有一个组件能正确接收并更新数据,另一个无响应;刷新页面后,生效的组件可能切换。
核心原因
- 前端回调覆盖:两个组件共用同一个WebSocket实例,且均通过赋值式设置
onmessage回调(websocket.onmessage = function(){...})。这种方式会直接覆盖之前的回调函数,最终只有最后执行赋值操作的组件回调会生效,刷新页面后组件挂载顺序可能变化,导致生效组件切换。 - 服务器变量冲突:
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
相关产品推荐
相关产品推荐

