useEffect 完整的执行过程
创建 effect 和保存 effect
首先在 render 阶段的 beginWork 方法中根据 workInProgress.tag 为 FunctionComponent 类型的组件会调用 renderWithHooks 方法执行组件然后拿到组件的执行结果创建 workInProgress fiber。而在执行组件的过程中遇到 useEffect 会根据 mount 还是 update 来判断是调用 mountEffect 还是 updateEffect。
其目的都是调用 pushEffect 方法创建 effect 对象,该对象包含 tag、create、destory、deps 和 next 属性。tag 标识是用来区分该 effect 对应的是 useEffect 还是 useLayoutEffect。HookPassive 表示 useEffect 的 tag,而 HookLayout 表示 useLayoutEffect。create 用来保存传入的回调函数。destory 用来保存回调函数的执行结果对应的销毁函数。deps 保存传入的依赖项。next 指针用于链接下一个 next 构成单项环状链表。同时还会将创建的 effect 插入到 workInProgress fiber 的 updateQueue.lastEffect 构成的单向环状链表中,lastEffect 属性始终指向最后一个插入的 effect。
最后创建的 effect 对象将保存到 hook.memoizedState 属性上。
执行 effect
在 commit 阶段的 beforeMutation 阶段之前,会先赋值 rootDoesHavePassiveEffects 属性为 true,再通过 scheduleCallback 以 normalPriority 调度 flushPassiveEffects 函数。
在 commit 阶段的 layout 阶段之后会赋值 rootWithPendingPassiveEffects 为 rootFiber,接下来等待 flushPassiveEffects 的执行。
在 flushPassiveEffects 方法中会执行 commitPassiveUnmountEffects 和 commitPassiveMountEffects 来分别调用 useEffect 的销毁和回调函数。
过程就是遍历 current fiber 的 updateQueue.lastEffect 属性上保存由 effect构成的单向环状链表,从第一个 effect 依次执行到最后一个 effect。
销毁函数就是执行 destory 函数,回调函数就是 create 函数。