Skip to content

React@v19源码---Hooks触发时机 #6

@MyPrototypeWhat

Description

@MyPrototypeWhat

触发时机

hooks 都写在函数式组件内,所以肯定在执行组件的时候触发,也就是在 render 阶段,通过 renderWithHooks 函数执行函数式组件

export function renderWithHooks<Props, SecondArg>(
  current: Fiber | null,
  workInProgress: Fiber,
  Component: (p: Props, arg: SecondArg) => any,
  props: Props,
  secondArg: SecondArg,
  nextRenderLanes: Lanes
): any {
  // ...
  renderLanes = nextRenderLanes;
  // 这个全局变量很关键,为当前执行的fiber
  currentlyRenderingFiber = workInProgress;
  // 清除新节点的三个属性
  workInProgress.memoizedState = null;
  workInProgress.updateQueue = null;
  workInProgress.lanes = NoLanes;
  // ...
  // 保存着所有hooks
  ReactSharedInternals.H =
    // 判断是 渲染还是更新,调用不同的dispatcher
    current === null || current.memoizedState === null
      ? HooksDispatcherOnMount
      : HooksDispatcherOnUpdate;
  // ...
  let children = Component(props, secondArg);
  // 清空相关变量和在dev环境下检查hooks是否正确执行
  finishRenderingHooks(current, workInProgress, Component);
  return children;
}

可以看到 hooks 在渲染阶段和更新阶段执行的不是同一个函数

const HooksDispatcherOnMount: Dispatcher = {
  readContext,
  use,
  useCallback: mountCallback,
  useContext: readContext,
  useEffect: mountEffect,
  useImperativeHandle: mountImperativeHandle,
  useLayoutEffect: mountLayoutEffect,
  useInsertionEffect: mountInsertionEffect,
  useMemo: mountMemo,
  useReducer: mountReducer,
  useRef: mountRef,
  useState: mountState,
  useDebugValue: mountDebugValue,
  useDeferredValue: mountDeferredValue,
  useTransition: mountTransition,
  useSyncExternalStore: mountSyncExternalStore,
  useId: mountId,
};
const HooksDispatcherOnUpdate: Dispatcher = {
  readContext,
  use,
  useCallback: updateCallback,
  useContext: readContext,
  useEffect: updateEffect,
  useImperativeHandle: updateImperativeHandle,
  useInsertionEffect: updateInsertionEffect,
  useLayoutEffect: updateLayoutEffect,
  useMemo: updateMemo,
  useReducer: updateReducer,
  useRef: updateRef,
  useState: updateState,
  useDebugValue: updateDebugValue,
  useDeferredValue: updateDeferredValue,
  useTransition: updateTransition,
  useSyncExternalStore: updateSyncExternalStore,
  useId: updateId,
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions