调用相同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完全相同,也会触发一次额外的渲染(仅开发模式)
对应你的代码流程:
- 初始渲染后,
useEffect触发,调用setNumber(1),state从0变为1,触发第二次渲染 - 第二次渲染后,
useEffect再次触发,调用setNumber(1)——此时新值与当前state一致,但React 18开发模式的Strict Mode会强制触发一次额外渲染,于是出现第三次的1 one和1 three打印 - 第三次渲染时,因为
setNumber(1)未改变state值,且依赖数组无更新,useEffect不会执行,所以没有1 two的打印
注意:这种额外渲染仅在开发模式存在,生产环境中React会跳过这些重复操作,不会产生多余渲染。
内容的提问来源于stack exchange,提问作者gushers
相关产品推荐
相关产品推荐

