resolveCurrentlyRenderingFiber

返回当前正在渲染的组件对应的Fiber,也就是当前FunctionalComponent对应的Fiber,在prepareToUseHooks时设置

createWorkInProgressHook

workInProgressHook在每次finishHooks的时候会被重置为null所以对于每个FunctionalComponent中的第一个Hooks调用,他调用createWorkInProgressHook的时候,肯定符合workInProgressHook === null,而第二个Hooks调用开始,肯定不符合该条件。

firstWorkInProgressHook时用来记录当前FunctionalComponent中第一个Hook调用对应的Hook对象。

该方法主要就是用来生产workInProgressHook对象的,这个跟FiberworkInProgress非常类似,对于整个React应用,我们把每个节点按照Fiber对象的形式来进行拆分然后进行更新,以及信息记录,比如两个最重要的数据记录:

  • Fiber.memoizedState
  • Fiber.memoizedProps

分别记录上次渲染时的stateprops

在Hooks体系中,我们对一个FunctionalComponent中每个Hook调用进行单元拆分,分别为他们创建Hook对象,用来记录他们的state,这就是我们能够通过useState记录状态原理。

那么同理,我们有createHookcloneHook分别对应创建复用Hook对象的数据结构如下:

function createHook(): Hook {
  return {
    memoizedState: null,

    baseState: null,
    queue: null,
    baseUpdate: null,

    next: null,
  };
}

相比Fiber还是简单很多了的。

这里需要注意isReRender这个变量,他是用来记录是否时重复渲染的,注意他被设置为true的条件:

  • workInProgressHook不存在并且firstWorkInProgressHook存在
  • workInProgressHook.next存在

这两种情况都说明了当前组件在这个渲染周期中已经被执行过一次了

function resolveCurrentlyRenderingFiber(): Fiber {
  invariant(
    currentlyRenderingFiber !== null,
    'Hooks can only be called inside the body of a function component.',
  );
  return currentlyRenderingFiber;
}

function createWorkInProgressHook(): Hook {
  if (workInProgressHook === null) {
    // This is the first hook in the list
    if (firstWorkInProgressHook === null) {
      isReRender = false;
      currentHook = firstCurrentHook;
      if (currentHook === null) {
        // This is a newly mounted hook
        workInProgressHook = createHook();
      } else {
        // Clone the current hook.
        workInProgressHook = cloneHook(currentHook);
      }
      firstWorkInProgressHook = workInProgressHook;
    } else {
      // There's already a work-in-progress. Reuse it.
      isReRender = true;
      currentHook = firstCurrentHook;
      workInProgressHook = firstWorkInProgressHook;
    }
  } else {
    if (workInProgressHook.next === null) {
      isReRender = false;
      let hook;
      if (currentHook === null) {
        // This is a newly mounted hook
        hook = createHook();
      } else {
        currentHook = currentHook.next;
        if (currentHook === null) {
          // This is a newly mounted hook
          hook = createHook();
        } else {
          // Clone the current hook.
          hook = cloneHook(currentHook);
        }
      }
      // Append to the end of the list
      workInProgressHook = workInProgressHook.next = hook;
    } else {
      // There's already a work-in-progress. Reuse it.
      isReRender = true;
      workInProgressHook = workInProgressHook.next;
      currentHook = currentHook !== null ? currentHook.next : null;
    }
  }
  return workInProgressHook;
}

results matching ""

    No results matching ""