React Hooks两次取反切换布尔状态触发useEffect的原因咨询
问题核心原因解答
这个差异的本质是你混淆了「直接传递状态值更新」和「基于更新前最新状态计算新值」的区别,以及React合并状态更新的规则:
先明确基础前提
在同一个事件回调的执行上下文里,所有从闭包捕获的状态变量都是当前渲染周期的固定值,调用setState不会立即修改当前作用域里的状态变量,只是向React提交更新请求。
第一段代码(触发useEffect)的执行逻辑
你当前渲染周期里bool的取值是false,所以点击回调里的两次setBool(!bool),本质上都是传入了固定值true,等价于:
// 两次都是基于当前闭包里的bool=false计算出true setBool(true); setBool(true);
React合并同批次更新时,最终的状态结果是true,和更新前的false存在差异,所以会触发组件重渲染,依赖bool的useEffect自然会执行。
你误以为两次!bool会把状态翻两次回到初始值,这是错误的认知:只有使用函数式更新,才会基于上一次更新后的状态计算新值。如果你把第一段代码改成下面的写法,最终状态会回到false,useEffect也不会触发:
onClick={() => { setBool(prev => !prev); // 第一次更新prev=false → 新值true setBool(prev => !prev); // 第二次更新prev=true → 新值false }}
第二段代码(不触发useEffect)的执行逻辑
你两次传入的固定值分别是true和false,React合并更新后最终的状态是false,和更新前的状态完全一致,React会跳过本次重渲染(bail out),所以useEffect不会执行。
内容的提问来源于stack exchange,提问作者user3451848
相关产品推荐
相关产品推荐

