React useState重复设置相同状态值时的重渲染机制疑问
React状态更新疑惑:重复设置相同值为何触发第二次重渲染?
我用一个简单计算器示例验证React state的工作机制,初始值设为1:
- 第一次点击+按钮,控制台输出“Run”,计算器显示“2”;
- 第二次点击+按钮,控制台仍输出“Run”和“2”,计算器还是显示“2”;
- 继续点击+按钮,控制台无任何输出。
对应的代码如下:
import {useState} from "react"; const App = () => { console.log("Run") const [counter, setCounter] = useState(1); console.log(counter) const addHandler = () => { setCounter(2); }; const subtractHandler = () => { setCounter(counter - 1); }; return <div className="app"> <h1>{counter}</h1> <button onClick={addHandler}>+</button> <button onClick={subtractHandler}>-</button> </div> }; export default App;
我的疑惑是:第一次点击后counter已经是2了,第二次点击+按钮再次设置counter为2时,为什么控制台还会输出“Run”和“2”?按我的理解,状态变量变更才会触发组件重渲染啊。
核心原因:React的状态更新批处理与重渲染优化时机
这其实是React的状态更新批处理和重渲染优化延迟性导致的:
第一次点击后的状态与闭包
第一次点击+按钮时,addHandler里的setCounter(2)触发状态更新,组件重渲染,此时counter变为2,同时生成了新的addHandler闭包(这个闭包绑定的counter值是2)。第二次点击的更新逻辑
第二次点击+按钮时,调用的是新生成的addHandler,执行setCounter(2)。在同步更新场景(比如点击事件触发的更新)下,React不会在调用setState时立刻判断新值是否与当前状态相等,而是会先将更新加入队列并触发一次重渲染,之后才会启用“相同值不触发重渲染”的优化逻辑。后续点击的优化生效
第二次重渲染完成后,新的addHandler闭包绑定的counter还是2。第三次点击+按钮时,React已经完成了前一次的状态对比校验,此时再调用setCounter(2),会直接跳过状态更新和重渲染,所以控制台没有输出。
简单总结:React的“相同状态值不触发重渲染”优化,在连续的同步更新中不会立刻生效,需要经过一次重渲染后,后续的相同值更新才会被拦截。
内容的提问来源于stack exchange,提问作者Tobin
相关产品推荐
相关产品推荐

