You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React reducer状态数组追加元素时每次新增元素重复翻倍

问题根因

你的reducer写法本身没有问题,数组重复翻倍的核心原因是socket事件监听器被重复注册,同一条消息触发了多次dispatch,最终表现为列表元素倍增:

  • 你写的socket.on事件绑定放在useEffect里,但没有写清理逻辑移除旧的监听器
  • 你把messages加入了useEffect的依赖数组:每次新消息dispatch后,Redux存储的messagelist更新,组件重渲染,messages引用变化就会触发useEffect重新执行,新增一个socket监听器

实际触发的倍增流程:

  1. 组件首次挂载,注册1个socket监听器
  2. 第1条消息到达,1个监听器触发,dispatch1次,列表长度变为1;列表更新触发重渲染,useEffect重跑,再注册1个新监听器,此时总共有2个监听器
  3. 第2条消息到达,2个监听器同时触发,各dispatch1次,列表一次性加2条,总长度变为3;列表更新再次触发重渲染,useEffect重跑再新增2个监听器,总共有4个监听器
  4. 后续消息到达时,监听器数量呈指数级上涨,每次dispatch的次数翻倍,最终表现为列表元素每次更新就重复翻倍
修复方案

修改messagelist.js中的useEffect逻辑:

  1. 移除依赖数组中不必要的messages依赖,socket事件绑定仅需在组件挂载时执行一次
  2. 增加useEffect清理函数,每次effect重跑、组件卸载前主动移除已绑定的socket监听器,避免重复绑定

修复后的代码片段:

const messages = useSelector((state) => state.messagelist)
const dispatch = useDispatch()

useEffect(() => {
  const handleReceiveMessage = (payload) => {
    console.log("socket payload", payload);
    dispatch({type:"newMessage", payload: payload})
  }
  // 绑定事件监听
  socket.on("user-to-admin", handleReceiveMessage)
  // 清理函数:移除旧的监听
  return () => {
    socket.off("user-to-admin", handleReceiveMessage)
  }
}, [dispatch]) // dispatch是引用稳定值,不会触发effect重复执行

let list = () => {
  return messages.map((e) => <ChatBubble who={e.who} message={e.message} />);
};
return <ul>{list()}</ul>

额外可以清理的冗余代码:你定义的const [data, setData] = useState([])全程没有实际使用,对应的data === undefined判断也是无效逻辑,可以直接删除。

内容的提问来源于stack exchange,提问作者Karthik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:27:09