使用Socket.io、React与Express时重复接收数据的问题如何解决?
Socket.io重复接收数据问题的解决方案
问题原因
React函数组件每次渲染时,都会执行组件内部的所有代码。你的代码中,socket.emit("server")和socket.on("server", ...)直接写在组件顶层,再加上socket是组件外创建的全局实例,就会导致:
- 每次组件渲染都重复绑定同一个事件的监听器,服务端返回的数据会被多个监听器同时接收,造成重复打印
- 每次组件渲染都触发一次
socket.emit("server"),服务端会多次响应并发送相同数据
解决方法
使用React的useEffect钩子,将Socket.io的逻辑限制在组件挂载时仅执行一次,并在组件卸载时清理监听器,避免重复绑定和内存泄漏。
修改后的React客户端代码
import { io } from "socket.io-client"; import { useEffect } from "react"; const socket = io("http://localhost:8000", { transports: ["websocket"] }); const Home = () => { useEffect(() => { // 组件挂载时仅发送一次请求 socket.emit("server"); // 定义事件处理函数,方便后续移除监听 const handleServerData = (data) => { console.log(data); }; socket.on("server", handleServerData); // 组件卸载时移除监听器 return () => { socket.off("server", handleServerData); }; }, []); // 空依赖数组确保该逻辑仅在组件挂载时执行一次 return ( <div> <h1>hello</h1> </div> ); }; export default Home;
服务端代码无需修改
你的Express服务端逻辑是正常的,仅在收到客户端的server事件时广播数据,问题根源完全在客户端的重复绑定逻辑。
修改后,组件只会在挂载时绑定一次监听器、发送一次请求,服务端返回的数据就只会被打印一次,不会再出现重复输出的情况。
内容的提问来源于stack exchange,提问作者MR.Jeon
相关产品推荐
相关产品推荐

