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

设置状态为当前值时触发Too many re-renders,与React文档描述不符

问题解析:为什么setFoo(foo)会导致无限重渲染?

首先明确核心误解:你混淆了状态更新的触发时机和React文档描述的适用场景。

文档描述的适用场景

React文档提到的“设置状态为当前值会跳过重渲染”,针对的是在事件处理函数、useEffect、异步回调这类非渲染同步流程中调用setState的情况。比如点击按钮时调用setFoo(foo),此时React会检查状态值是否变化,确认无变化后,最多额外调用一次组件函数,但不会触发DOM更新,也不会形成循环。

你的代码为什么会无限循环?

你在组件函数的顶层同步调用setFoo(foo),这会触发以下循环:

  1. 组件首次渲染时,执行到setFoo(foo),启动React的更新流程;
  2. 即使状态值未变化,React仍会调用组件函数以检查是否需要更新;
  3. 组件函数再次执行时,又会触发setFoo(foo),再次启动更新流程;
  4. 该循环持续触发,直到React触发“Too many re-renders”的保护机制。

不管你是否使用memo、StrictMode,或是用函数式更新setFoo(val => val),结果都是一样的——只要在组件渲染的同步流程里调用setState,无论是否改变状态,都会触发更新流程,进而导致循环。

关于“结果会被丢弃”的理解

文档里的“结果会被丢弃”,指的是DOM更新的结果。也就是说,当状态无变化时,即使组件函数被额外调用一次,React不会把这次的输出更新到DOM上。但在你的场景里,组件函数被反复调用是因为每次调用都触发了setState,这已经不是单次的额外调用,而是无限循环的触发。

正确的写法

要避免这种情况,必须把setState放在非渲染同步流程的逻辑里,比如事件处理、带合适依赖项的useEffect:

const Component = memo(function () {
    const [foo, setFoo] = useState('x');

    // 仅在组件挂载时执行一次
    useEffect(() => {
        setFoo(foo); // 状态无变化,React会跳过DOM更新,不会触发循环
    }, []);

    return null;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:22:51