React中useEffect存在时useState更新回调与同步代码执行顺序异常咨询
执行顺序差异的核心原因
这个现象是React 17及更早版本的Legacy渲染模式下,批量更新机制的特殊实现逻辑导致的:
无useEffect时的执行逻辑
当你注释掉空依赖useEffect后,组件首次渲染完成后没有待处理的更新任务,默认上下文下批量更新开关isBatchingUpdates值为false。
你点击按钮触发回调后:
- 先执行
onChange内的setState1,因为批量更新未开启,React会同步执行你传入的状态更新函数,直接打印onChange set state完成状态更新 - 再执行
onChange2,打印onChange2
所以最终日志顺序是onChange set state在前,onChange2在后。
有useEffect时的执行逻辑
当你保留useEffect时,组件首次挂载完成后会触发useEffect执行,内部的setState会触发一次组件重渲染:
React处理useEffect内的更新时,会临时开启批量更新,本次重渲染完成后,isBatchingUpdates开关的重置逻辑存在延迟,导致后续第一次用户触发的事件回调执行时,批量更新开关依然处于开启状态。
此时你点击按钮触发回调后:
- 先执行
onChange内的setState1,因为批量更新已开启,React不会同步执行更新函数,而是先把更新推入待处理队列,继续执行后续同步代码 - 再执行
onChange2,打印onChange2 - 等整个onClick回调执行完成后,React才会批量处理队列中的更新,执行
setState1的更新函数,打印onChange set state
所以最终日志顺序是onChange2在前,onChange set state在后。
补充说明
该差异仅存在于React 17及更早的Legacy模式中,React 18默认开启自动批量更新,不管是否有该useEffect,点击按钮的日志都会是onChange2在前,更新函数日志在后。
内容的提问来源于stack exchange,提问作者Dmitriy Glazkov
相关产品推荐
相关产品推荐

