为什么React useState传入函数更新状态可实现多次累计更新?
核心差异本质
两种写法的根本区别是获取状态值的来源不同,结合React的状态批处理机制就产生了不同的结果。
第一种传值写法为什么只减1
组件每次渲染都会生成独立的闭包环境,当前渲染周期里你拿到的count是固定不变的快照值:
// 本次渲染count的快照值是0 const [count,setCount] = useState(0) // 两次setCount传入的都是 0-1 = -1 setCount(count-1) setCount(count-1)
React会把同一同步流程里的所有状态更新合并批处理,遇到两次传入相同值的更新,最终只会生效一次,所以count最终只会从0变成-1,也就是仅减1。
第二种传函数写法为什么能正确减2
当你给状态更新函数传入回调时,React会把这个回调存入更新队列,批处理时会按调用顺序依次执行:
setCount(prevCount => prevCount-1) setCount(prevCount => prevCount-1)
每个回调的入参prevCount都是上一步更新完成后的最新状态值,不是当前渲染的快照值:
- 第一次执行回调,拿到初始值0,返回0-1 = -1
- 第二次执行回调,拿到上一步返回的-1,返回-1-1 = -2
所以最终count会变成-2,正确完成两次减1的操作。
总结
如果你的新状态需要依赖旧状态计算得出,优先使用函数式更新写法,可以避免闭包旧值导致的更新异常。
内容的提问来源于stack exchange,提问作者Sinadin Shan
相关产品推荐
相关产品推荐

