React深入8-源码4 (useEffect,useLayou

2022-03-10  本文已影响0人  申_9a33

上一篇博客,初步使用了 useReducer, useState; 现在接着实现useEffect, useLayoutEffect


实现useEffect和useLayoutEffect

// src\react\hooks.ts

export function renderHooks(wip:any) {
  currentlyRenderingFiber = wip as IFiber;
  currentlyRenderingFiber.memoizedState = null;
  currentlyRenderingFiber.updateQueueOfEffect = [];
  currentlyRenderingFiber.updateQueueOfLayout = [];
  workInProgressHook = null;
}

export function useEffect(create:Function, deps:Array<any> | null) {
  updateEffectIml(HookPassive, create, deps);
}

export function useLayoutEffect(create:Function, deps:Array<any> | null) {
  updateEffectIml(HookLayout, create, deps);
}

function updateEffectIml(hookFlags:number, create:Function, deps:Array<any> | null) {
  const hook = updateWorkInProgressHook();

  if (!hook.memoizedState) {
    // 第一次渲染
    hook.memoizedState = { create, deps, HookLayout };
  } else {
    if (areHookInputsEqual(hook.memoizedState.deps, deps)) {
      return;
    }
    hook.memoizedState = { create, deps, HookLayout };
  }

  if (hookFlags & HookLayout) {
    currentlyRenderingFiber?.updateQueueOfLayout.push(hook.memoizedState);
  } else if (hookFlags & HookPassive) {
    currentlyRenderingFiber?.updateQueueOfEffect.push(hook.memoizedState);
  }
}

修改commit 阶段调用updateQueueOfxxx里面的create

// src\react\ReactFiberWorkLoop.ts
function commitWorker(wip:any) {
  // ...

  const { stateNode, flags, type } = wip;

  if (isFunction(type)) {
    invokesHooks(wip);
  }
  // ...
}

function invokesHooks(wip:any) {
  const { updateQueueOfEffect, updateQueueOfLayout } = wip;

  if (updateQueueOfEffect && updateQueueOfEffect.length) {
    updateQueueOfEffect.forEach(({ create }:any) => schedulerCallback(() => {
      create();
      return true;
    }));
  }

  if (updateQueueOfLayout && updateQueueOfLayout.length) {
    updateQueueOfLayout.forEach(({ create }:any) => create());
  }
}

源码

上一篇 下一篇

猜你喜欢

热点阅读