React中setState触发组件重新渲染的底层原理是什么?
useState的setState如何触发组件重新渲染?
你提到的“setState直接调用渲染”其实是个常见误解,它的底层逻辑涉及React核心的fiber架构和调度机制,具体流程可以拆解为以下几个步骤:
1. 组件挂载时的绑定
当组件首次渲染时,React会为其创建一个fiber节点——这是React内部管理组件的核心数据结构,里面保存了组件的状态、更新队列、DOM信息、以及和其他fiber节点的层级关联。
调用useState时,React会把初始状态和对应的setState函数绑定到当前组件的fiber节点上,确保后续调用setState时能找到对应的组件上下文。
2. setState触发更新队列
当你调用setState(newValue)时,本质是执行了React封装的内部更新函数:
- 它会创建一个更新对象,包含新的状态值(如果是函数式更新,会先执行函数拿到最终值);
- 把这个更新对象添加到当前组件fiber节点的更新队列中排队。
3. 调度更新任务
更新对象入队后,React会调用scheduleUpdateOnFiber函数,这是触发更新的核心入口:
- 它会给当前fiber节点打上“需要更新”的标记;
- 根据更新的优先级(比如用户点击输入是高优先级,网络请求回调是低优先级),把更新任务交给**调度器(Scheduler)**处理。调度器会决定任务的执行时机,高优先级任务会优先执行,甚至可以打断正在进行的低优先级渲染,避免阻塞主线程(这也是React 18并发模式的核心)。
4. 调和(Reconciliation)阶段
当调度器安排好任务后,React进入调和阶段:
- 从标记为更新的fiber节点开始,遍历整个fiber树,对比新旧fiber节点的状态、props等,计算出哪些组件需要重新渲染,哪些DOM节点需要修改;
- 这个过程是可中断的,React会在浏览器空闲时继续执行,避免卡顿。
5. 提交(Commit)阶段
调和阶段完成后,React进入提交阶段:
- 把调和阶段计算出的DOM变更应用到真实DOM上;
- 触发组件的副作用钩子(比如
useEffect),完成组件的重新渲染。
为什么直接修改状态不会触发渲染?
如果你直接修改useState返回的状态变量(比如count = count + 1),React不会创建对应的更新对象,也不会标记fiber节点为需要更新,调度器不会触发后续的调和-提交流程,自然不会触发组件重新渲染。
内容的提问来源于stack exchange,提问作者noob_developer
相关产品推荐
相关产品推荐

