You need to enable JavaScript to run this app. 为什么依赖[currentData]的useEffect会导致组件无限重渲染?
优惠活动
大模型
产品
解决方案
定价
更多

为什么依赖[currentData]的useEffect会导致组件无限重渲染?

useEffect 依赖数组的比对规则

React 对 useEffect 依赖数组的每一项执行与 Object.is 完全等价的浅比较,不存在内置的深度比对逻辑:

  • 基本类型(字符串、数字、布尔值等)直接比对值本身
  • 引用类型(对象、数组、函数等)直接比对内存引用地址,即便两个对象的属性、属性值完全一致,只要引用不同就会被判定为依赖变化
  • 只要任意一个依赖项与上一次渲染周期的对应值不相等,React 就会在本次 UI 渲染提交完成后,触发对应 useEffect 的回调执行
代码触发无限重渲染的具体原因

这段代码的无限循环来自两个叠加的问题:

  1. 状态更新函数的参数误用
    React 函数组件中由 useState 返回的 setData 仅接收单个参数,第二个传入的参数会被直接忽略。你写的 setData({ ...currentData }, { data }) 实际生效的新状态,是通过展开语法生成的全新对象 { ...currentData }——哪怕这个对象的所有属性和旧的 currentData 完全一致,它的内存引用也是全新的。
  2. 循环触发的完整链路
    • 组件首次挂载,执行 effect 回调,发起 getMyData 异步请求
    • 异步请求返回后调用 setData,生成全新引用的 state 对象,触发组件重渲染
    • 重渲染时生成的新 currentData 变量,因为引用和上一次渲染周期的 currentData 不一致,被 React 判定为依赖发生变化
    • 对应 effect 再次触发执行,重新发起异步请求、再次调用 setData 生成新的 state,重复上述流程形成死循环
可落地的修复方案
  • 如果仅需要在组件挂载时拉取一次数据,直接将依赖数组改为空数组 [],移除对 currentData 的依赖即可
  • 如果需要基于旧状态合并新拉取的数据,优先使用函数式状态更新写法,避免在 effect 中直接引用旧状态值引入不必要的依赖:
    setData((prev) => ({ ...prev, data }))
    
  • 如果业务逻辑确实需要监听 currentData 变化才重新拉取数据,可以通过 useMemo 固定值未变化时的对象引用,避免无意义的引用变更触发 effect 执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.06 14:24:04