React异步函数状态更新疑问:两种delay场景下pending值差异解析
React异步状态更新中pending值差异的原因分析
核心问题出在React组件状态的闭包捕获特性,结合异步操作的执行顺序拆解如下:
1. 初始执行时的闭包快照
当点击按钮触发handleClick时,这个函数会捕获当前组件渲染周期的pending值(初始为0)。哪怕之后调用setPending(p=>p+1)更新了状态,handleClick内部的pending变量依然是最初的0——闭包保存的是函数创建时的状态快照,状态更新不会修改已存在的变量值。
2. 第一种场景:await delay(pending*3000)
这里pending是闭包捕获的0,所以pending*3000等于0,delay(0)相当于无等待,代码立刻执行后续逻辑:
setPending(p=>p-1):函数式更新会拿到当前最新的pending值(刚被setPending(p=>p+1)更新为1),减1后回到0;setCompleted(c=>c+1)同步执行,completed立刻加1。
最终表现就是pending始终为0,completed立即变化。
3. 第二种场景:await delay(pending*3000+3000)
同样,pending是闭包捕获的0,计算后得到3000毫秒(3秒)的等待时间:
- 等待期间,React完成
setPending(p=>p+1)的状态更新,组件重新渲染,pending变为1; - 3秒后,
setPending(p=>p-1)拿到最新的pending值(1),减1后回到0; setCompleted(c=>c+1)执行,completed加1。
这就符合你预期的“pending先加1,3秒后减1且completed加1”的行为。
关键总结
- 函数式状态更新(
setState(prev => ...))能获取最新状态值,不受闭包影响; - 异步操作前捕获的状态变量,是函数创建时的快照值,不会随后续状态更新改变。
内容的提问来源于stack exchange,提问作者egg24
相关产品推荐
相关产品推荐

