使用useEffect接收Socket.io消息不稳定及在线用户数异常求助
Socket.io聊天应用问题修复:消息展示不稳定与在线用户数异常
一、消息展示不稳定的问题修复
问题根源
- 异步状态更新导致旧值误用:
useEffect中socket.on("receive_message")回调里,调用displayMessage(messageReceived)时,setMessageReceived(data)是异步操作,此时messageReceived仍是更新前的旧值,导致展示的不是最新消息。 - React中直接操作DOM的风险:通过
document.querySelector获取DOM并手动创建节点的方式,违背React状态驱动渲染的理念,易造成DOM与状态不同步,引发不稳定展示。 - 不必要的监听重复绑定:
useEffect依赖数组包含setMessageReceived,每次状态更新都会触发useEffect重新执行(先移除监听再绑定),可能导致消息丢失或重复监听。
修复代码(客户端)
import io from 'socket.io-client'; import { useEffect, useState } from 'react'; function App() { const [messageReceived, setMessageReceived] = useState(""); const [liveUsers, setLiveUsers] = useState(0); const [messagesList, setMessagesList] = useState([]); const [socket, setSocket] = useState(null); // 初始化Socket连接 useEffect(() => { const newSocket = io.connect("http://localhost:3001"); setSocket(newSocket); return () => { newSocket.disconnect(); }; }, []); // 监听Socket事件 useEffect(() => { if (!socket) return; const handleReceiveMessage = (data) => { setMessageReceived(data); setMessagesList(prev => [...prev, data]); }; const handleReceiveUsers = (data) => { setLiveUsers(data); }; socket.on("receive_message", handleReceiveMessage); socket.on("receive_users", handleReceiveUsers); return () => { socket.off("receive_message", handleReceiveMessage); socket.off("receive_users", handleReceiveUsers); }; }, [socket]); const sendMessage = () => { const textInput = document.querySelector('.textInput'); const text = textInput.value.trim(); if (!text) return; setMessagesList(prev => [...prev, text]); socket.emit("send_message", text); textInput.value = ""; }; return ( <div className="App"> <h2 className="text-white font-bold" style={{ color: "white", marginTop: 10 }}> 在线用户: {liveUsers} </h2> <div className='messages' style={{ border: '1px solid #ccc', padding: '10px', height: '300px', overflowY: 'auto' }}> {messagesList.map((msg, index) => ( <div key={index}>{msg}</div> ))} </div> <input className="textInput text-gray-500 font-bold" style={{ height: 38, marginRight: 10, padding: 5, width: 1000 }} placeholder='消息' /> <button id="name" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={sendMessage} > 发送 </button> <h1>最新消息: {messageReceived}</h1> </div> ); } export default App;
二、在线用户数异常增加的问题修复
问题根源
- 断开连接时无法发送更新:用户断开时,
socket.emit("receive_users", count)无法成功发送(此时socket已断开),导致其他客户端无法同步用户数减少的状态。 - 连接时仅通知当前用户:新用户连接时,仅通过
socket.emit通知当前用户,其他在线用户无法同步最新在线数。
修复代码(服务端)
const express = require('express'); const app = express(); const http = require("http"); const { Server } = require('socket.io'); const cors = require("cors"); app.use(cors()); const server = http.createServer(app); const io = new Server(server, { cors: { origin: "http://localhost:3000", methods: ["GET", "POST"], }, }); let count = 0; io.on("connection", (socket) => { console.log(`用户已连接: ${socket.id}`); count++; // 通知所有客户端更新在线用户数 io.emit("receive_users", count); socket.on("send_message", (data) => { socket.broadcast.emit("receive_message", data); }); socket.on("disconnect", () => { console.log("用户已断开连接"); count--; // 通知所有客户端更新在线用户数 io.emit("receive_users", count); }); }); server.listen(3001, () => { console.log("监听端口3001") });
内容的提问来源于stack exchange,提问作者jlc
相关产品推荐
相关产品推荐

