Socket后端运行正常但React前端接收消息异常求助
Socket.IO 前端消息接收异常解决方案
问题概述
后端Socket.IO服务运行正常(sendingMessage事件中console.log(data)可正常输出),但React前端在useEffect钩子中监听receiveMessage事件时,无法触发console.log(message),偶尔能工作但刷新页面后失效,消息发送功能正常。
后端代码
const userSocketMap = {}; io.on("connection", (socket) => { socket.on("register-id", (username) => { userSocketMap[username] = socket.id; console.log(socket.id); }); socket.on("sendingMessage", (data) => { const { sender, receiver, message } = data; const receiverId = userSocketMap[receiver]; if (receiverId) { console.log(data); console.log("当前接收方SocketID:", receiverId); // 新增调试日志 io.to(receiverId).emit("receiveMessage", data); } else { console.log("未找到接收方对应的Socket连接"); // 新增调试日志 } }); // 新增:清理断开连接的用户 socket.on("disconnect", () => { Object.keys(userSocketMap).forEach(username => { if (userSocketMap[username] === socket.id) { delete userSocketMap[username]; } }); }); }); server.listen(3000, () => { console.log(`Server running on http://localhost:3000`); });
前端相关代码
消息接收逻辑(组件内)
useEffect(() => { const handleMessageReceive = (data) => { const message = { sender: data.sender, receiver: data.receiver, message: data.message, timestamp: new Date(data.timestamp).toISOString().slice(11, 16), }; console.log(message); }; socket.on("receiveMessage", handleMessageReceive); return () => { socket.off("receiveMessage", handleMessageReceive); }; }, []);
Socket实例配置(socket.js)
import { io } from "socket.io-client"; const socket = io("http://localhost:3000"); // 新增:连接成功后自动注册用户 socket.on('connect', () => { console.log("当前前端SocketID:", socket.id); // 新增调试日志 const username = localStorage.getItem('username'); if (username) { socket.emit('register-id', username); } }); export { socket };
核心解决方案
- 刷新后强制重新注册用户:页面刷新会导致Socket连接重建,旧的
socket.id完全失效。必须在Socket触发connect事件后,重新发送register-id给后端,更新userSocketMap中的对应关系,确保后端拿到当前有效的socket.id。 - 清理无效Socket连接:后端新增
disconnect事件监听,当用户断开连接时从userSocketMap中删除对应条目,避免残留无效的socket.id导致消息发送到已断开的连接。 - 比对前后端SocketID:通过新增的调试日志,确认后端
sendingMessage事件中输出的receiverId与前端connect事件中输出的socket.id一致。如果不一致,说明用户未完成重新注册流程。 - 确保Socket实例全局唯一:当前配置已通过单例导出实现,无需修改,避免多实例导致事件监听分散失效。
内容的提问来源于stack exchange,提问作者Batyrlan
相关产品推荐
相关产品推荐

