React结合Socket.io开发时如何遍历渲染实时更新的消息数组?
问题原因
你遇到的渲染失效问题主要有两个核心原因:
- 普通变量不具备响应式能力:React仅会在
useState、useReducer等声明的响应式状态更新时触发组件重新渲染,你声明的itemArray是组件内的普通临时变量,不仅修改它不会触发页面更新,每次组件重渲染时还会被重置为空数组。 - 遍历逻辑没有返回渲染内容:你在
itemArray.map的回调中仅执行了console.log操作,没有返回任何要渲染的UI元素,就算数组有内容也不会在页面展示。
修正后完整代码
import { useEffect, useState } from "react"; import io from "socket.io-client"; import "./App.css"; let socket; const CONNECTION_PORT = "localhost:3001/"; function App() { const [loggedIn, setLoggedIn] = useState(false); const [room, setRoom] = useState(""); const [userName, setUserName] = useState(""); const [message, setMessage] = useState(""); // 用useState声明响应式的消息列表 const [messageList, setMessageList] = useState([]); useEffect(() => { socket = io(CONNECTION_PORT); const handleReceiveMessage = (data) => { // 不可变方式更新消息列表,触发组件重渲染 setMessageList(prev => [...prev, data]); console.log("Pong"); }; const handleAuthentication = (bool) => { if (bool === true) { setLoggedIn(true); } }; socket.on("receive-message", handleReceiveMessage); socket.on("authentication", handleAuthentication); // 组件卸载时清理监听、断开连接,避免内存泄漏 return () => { socket.off("receive-message", handleReceiveMessage); socket.off("authentication", handleAuthentication); socket.disconnect(); }; }, [CONNECTION_PORT]); const connectToRoom = () => { socket.emit("join-room", room, userName); }; const sendMessage = () => { socket.emit("send-message", message); // 发送后清空输入框 setMessage(""); }; return ( <div className="App"> {!loggedIn ? ( <div className="login"> <input type="text" placeholder="Name..." onChange={(e) => setUserName(e.target.value)} /> <input type="text" placeholder="Room..." onChange={(e) => setRoom(e.target.value)} /> <button onClick={connectToRoom}> Enter Chat</button> </div> ) : ( <div> <input type="text" placeholder="Send Message..." value={message} onChange={(e) => setMessage(e.target.value)} /> <button onClick={sendMessage}>Send Message</button> <div className="message-box"> {/* 遍历返回消息元素,添加唯一key */} {messageList.map((data, index) => ( <p key={index}>{data}</p> ))} </div> </div> )} </div> ); } export default App;
补充说明
如果需要展示消息发送者信息,可以调整服务端广播逻辑,把{ content: 消息内容, sender: 用户名 }这类结构化数据传递到前端,渲染时分别展示即可。
内容的提问来源于stack exchange,提问作者James Westhead
相关产品推荐
相关产品推荐

