1. React副作用机制全景解读
当我们在函数组件中使用useEffect时,实际上是在告诉React:"这段代码需要在组件渲染到屏幕之后执行"。这种声明式的副作用管理方式,与类组件中的生命周期方法有着本质区别。React的副作用系统建立在Fiber架构之上,通过调度机制实现了细粒度的控制。
最近在排查一个内存泄漏问题时,我不得不深入React源码探究Effect的执行机制。发现从组件的挂载、更新到卸载,React维护了一套精巧的副作用处理流程。比如在函数组件中,每次渲染都会生成新的effect对象,但React会通过依赖项比较来决定是否需要重新执行副作用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Effect核心实现流程拆解
2.1 初始化阶段:effect对象的创建
在函数组件执行过程中,当遇到useEffect调用时,React会在内存中创建一个effect对象。这个对象包含几个关键属性:
- create:副作用回调函数
- destroy:清理函数(由create返回)
- deps:依赖项数组
- tag:二进制标志位(标识effect类型)
javascript复制function mountEffect(create, deps) {
return mountEffectImpl(
UpdateEffect | PassiveEffect,
HookPassive,
create,
deps
);
}
在mountEffectImpl内部,React会将当前effect挂载到fiber节点的updateQueue链表中。值得注意的是,所有effect是以链表形式存储的,这为后续的顺序执行奠定了基础。
2.2 提交阶段:effect的调度与执行
React的渲染分为render阶段和commit阶段。effect的执行发生在commit阶段的后期,具体是在commitBeforeMutationEffects和commitMutationEffects等子阶段中。
在commitRootImpl函数中,React会执行以下关键操作:
- 调度flushPassiveEffects异步任务
- 处理layout effects(同步执行)
- 安排passive effects(异
