react Hooks(useEffect)实现原理 - 简单理解

useEffect

语法: useEffect(setup, dependencies?)
含义: useEffect 是一个 React Hook,它允许你 将组件与外部系统同步。

useEffect 源码简单理解

一、mountEffect 和 upadateEffect

useEffect 与其它 hooks 一样分为 mountEffect 和 upadateEffect 两个阶段

第一次执行 mountEffect
react Hooks(useEffect)实现原理 - 简单理解_第1张图片
后面执行 upadateEffect
react Hooks(useEffect)实现原理 - 简单理解_第2张图片
从代码中可以看出 mountEffect 和 upadateEffect 传参都是 函数 和 依赖数组,调用 mountEffectImplupdateEffectImpl
mountEffectImpl 和 updateEffectImpl 它们的四个入参一样。其中前面两个入参表示 tag 实现了指定的行为,具体可参考源码 ReactSideEffectTags.js 和 ReactHookEffectTags.js文件,暂时忽略。

二、mountEffectImpl 和 updateEffectImpl

mountEffectImpl

react Hooks(useEffect)实现原理 - 简单理解_第3张图片
以上代码中可以看出 执行 pushEffect 并将返回结果记录在 hook的memoizedState上

updateEffectImpl

react Hooks(useEffect)实现原理 - 简单理解_第4张图片
以下代码可以看出 当 currentHook 为空的时候,updateEffectImpl 的逻辑与 mountEffectImpl 的逻辑是一样。当 currentHook 不为空、依赖数组不为空时,判断依赖数组里的值是否有变化,若相等无变化则执行pushEffect。猜测这个时候的 hookFlags 指不执行这次 useEffect。

不管哪个阶段最终都执行 pushEffect 函数,那它是啥呢?

pushEffect

react Hooks(useEffect)实现原理 - 简单理解_第5张图片
这个函数首先根据入参声明了一个新的 effect 并返回。它实际是一个循环链表

Effect = {
  tag: HookEffectTag, // 一个二进制数,它将决定 effect 的行为
  create: () => (() => void) | void, // 绘制后应该运行的回调
  inst: (() => void) | void, // 用于确定是否应销毁和重新创建 effect
  deps: Array<mixed> | null, // 决定重绘制后是否执行的 deps
  next: Effect, // 函数组件中定义的下一个 effect 的引用
};

componentUpdateQueue : 存储 Effect 的全局变量
判断 componentUpdateQueue 是否为空:

  1. componentUpdateQueue 空:与 mountEffect 逻辑类似,它会创建一个空的 componentUpdateQueue,它其实是 {lastEffect: null},之后将 componentUpdateQueue.lastEffect 指向 effect.next,其实就是存了一下 effect
  2. componentUpdateQueue 不为空:
    2.1 lastEffect 为空:这种情况是新的渲染阶段的第一个 useEffect,逻辑处理和 componentUpdateQueue 为空时一致
    2.2 lastEffect 不为空:这种情况意味着这个组件有多个 useEffect,是第二个及其之后的 useEffect 会走到的分支,将 lastEffect 指向下一个 effect

最后 returen effect

小结

以上就是 useEffect 源码的大致流程。表面上到这里就结束啦。
但不难发现,useEffect 的很多功能在上面代码并没有实现。还有以上代码中的 pushEffect 之后又有哪些逻辑呢?componentUpdateQueue 存储 Effect 之后会在哪里被用到?

饿了,先干饭去,后面接着总结。未完待续。。。

你可能感兴趣的:(react,react.js,前端,前端框架)