React JS 向数组插入新对象时始终替换最后一项而非新增的问题
问题根因
你遇到的是React Hooks的闭包陷阱问题:你的useEffect依赖数组仅填写了props.conversation_id,只会在会话ID变化时重新执行,因此useEffect内部的messageListener函数永远捕获的是首次执行useEffect时的chatList初始值。每次收到新消息执行[...chatList, message]时,用的都是旧的初始列表,自然只会保留初始值+最新一条消息,看起来就像替换了最后一项。
解决方案
最优方案是使用setState的函数式更新语法,直接从状态的最新值计算新状态,不需要依赖外部的chatList变量,修改后代码如下:
const [chatList, setChatList] = useState(props.chatList ? props.chatList : []); useEffect(() => { const messageListener = (message) => { console.log('message',message); console.log('chatList',chatList); if(message.conversation_id == props.conversation_id){ // 改用函数式更新,直接读取最新的历史列表拼接新消息 setChatList(prevChatList => [...prevChatList, message]); } }; socket.on('myEventName', messageListener); return () => { socket.off('myEventName', messageListener); }; }, [props.conversation_id]);
如果不想用函数式更新,也可以把chatList加到useEffect的依赖数组中即可生效,但要注意每次依赖变化时都会重新注册监听函数,需要确保卸载逻辑正确移除旧监听,综合更推荐上面的函数式更新写法。
内容的提问来源于stack exchange,提问作者Devsi Odedra
相关产品推荐
相关产品推荐

