以下是 useEffect 原理的简洁总结,涵盖其核心机制和工作流程:
useEffect 原理总结
定义
useEffect 是 React Hooks 提供的副作用处理工具,用于在函数组件中执行渲染后的操作(如数据获取、订阅事件),替代类组件的生命周期方法。
核心原理
- 副作用调度:
- 将副作用逻辑封装在回调函数中,在组件渲染完成(commit 阶段)后异步执行。
- 通过 React 的 Fiber 架构管理,确保不阻塞 DOM 更新和浏览器绘制。
- 依赖项比较:
- 使用
Object.is()逐项比较当前依赖项数组(deps)与上一次渲染的依赖项(prevDeps)。 - 如果任意依赖项变化(
Object.is(dep, prevDep)返回false),触发副作用;否则跳过。
- 使用
- 执行流程:
- 挂载:首次渲染时直接运行副作用。
- 更新:依赖项变化时,先执行清理函数(若有),再运行新副作用。
- 卸载:组件移除时运行清理函数。
- 清理机制:
- 支持返回清理函数,在下次副作用运行前或组件卸载时同步执行,用于资源清理。
- 与渲染集成:
- 副作用存储在 Fiber 节点的
updateQueue中,在 DOM 更新后通过调度器异步触发。
- 副作用存储在 Fiber 节点的
工作机制
- 依赖项为空 (
[]):只在挂载和卸载时运行一次。 - 无依赖项 (
undefined):每次渲染后运行。 - 有依赖项 (
[dep1, dep2]):仅当依赖项变化时运行。 - 时机:
- 副作用:异步运行于 DOM 更新后。
- 清理:同步运行于下次副作用前或卸载时。
示例
useEffect(() => {
console.log('Effect');
return () => console.log('Cleanup');
}, [dep]);
dep变化时:Object.is(dep, prevDep)返回false。- 运行
Cleanup→ 运行Effect。
关键点
Object.is()的作用:判断依赖项是否变化,是触发副作用的决定性条件。- 核心目标:在适当时机执行副作用,保证组件状态与外部世界同步。
- 局限:只比较依赖项引用,无法感知对象内部变化,除非显式更新引用。
总结一句话
useEffect 通过 Object.is() 比较依赖项变化,在渲染后异步调度副作用,并在需要时同步清理,依托 Fiber 架构与 React 渲染流程无缝集成。
前端工程师、程序员

浙公网安备 33010602011771号