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

调用相同state值的setState后,React组件为何重复渲染?

React中state值未变化却触发额外重渲染的原因

问题代码

export function App(props) {
  const [number,setNumber] = useState(0);
  console.log(number,'one')
  useEffect(()=>{
    console.log(number,'two')
    setNumber(1);
  },[number]);
  console.log(number,'three')
  return (
    <div className='App'>
      {number}
    </div>
  );
}

完整可运行代码

const { useState, useEffect } = React;

function App(props) {
  const [number,setNumber] = useState(0);
  console.log(number,'one')
  useEffect(()=>{
    console.log(number,'two')
    setNumber(1);
  },[number]);
  console.log(number,'three')
  return (
    <div className='App'>
      {number}
    </div>
  );
}

ReactDOM.createRoot(document.querySelector("#root")).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>

预期输出

0 one
0 three
0 two
1 one
1 three
1 two

实际输出

0 one
0 three
0 two
1 one
1 three
1 two
1 one
1 three

原因分析

这是React 18开发模式下Strict Mode的刻意行为。

在React 18的开发环境中,Strict Mode会执行一系列操作帮助开发者检测潜在的副作用问题:

  • 两次调用组件渲染函数
  • 对useEffect执行「执行→清理→再执行」的循环
  • 即使调用setState传入的新值与当前state完全相同,也会触发一次额外的渲染(仅开发模式)

对应你的代码流程:

  1. 初始渲染后,useEffect触发,调用setNumber(1),state从0变为1,触发第二次渲染
  2. 第二次渲染后,useEffect再次触发,调用setNumber(1)——此时新值与当前state一致,但React 18开发模式的Strict Mode会强制触发一次额外渲染,于是出现第三次的1 one和1 three打印
  3. 第三次渲染时,因为setNumber(1)未改变state值,且依赖数组无更新,useEffect不会执行,所以没有1 two的打印

注意:这种额外渲染仅在开发模式存在,生产环境中React会跳过这些重复操作,不会产生多余渲染。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 17:57:32