点击:react git 链接
截止2024.8.22最新版本如下
React hooks
源码好深,hook封装位于packages/react-reconciler/src/ReactFiberHooks.js
hook的数据类型:
export type Hook = {
   
  memoizedState: any,
  baseState: any,
  baseQueue: Update<any, any> | null,
  queue: any,
  next: Hook | null,
};
HooksDispatcher
在 React 18 及更新的版本中,HooksDispatcher 是一个内部使用的调度器,它负责协调 React 组件的挂载(mount)和更新(update)过程中的 Hooks 调用。HooksDispatcherOnMount 和 HooksDispatcherOnUpdate 是 HooksDispatcher 在不同渲染阶段的实例,它们分别用于处理组件首次挂载和随后的更新。
 HooksDispatcherOnMount 和 HooksDispatcherOnUpdate 是 React 为了更好地控制组件渲染过程中 Hooks 的行为而引入的内部调度器实例。它们确保了 Hooks 在组件的不同生命周期阶段能够正确地执行。
HooksDispatcherOnMount
- HooksDispatcherOnMount是在组件首次挂载时使用的调度器实例。
- 在这个阶段,React 会调用组件内的所有 Hooks,例如 useState,useEffect,useContext等,并且是按照它们在代码中出现的顺序进行调用。
- 由于是首次渲染,useState会为每个 state 创建初始状态,useEffect会执行所有 effect 的逻辑(但不会清除,因为没有之前的 effect)。
  
HooksDispatcherOnUpdate
- HooksDispatcherOnUpdate是在组件更新时使用的调度器实例。
- 在更新阶段,React 同样会调用组件内的所有 Hooks,但这次调用是有条件的。React 会根据调度器来判断 Hooks 是否需要被调用。
- 例如,useState会返回当前的状态值,useEffect会根据 effect 的依赖项来决定是否执行 effect。
- 更新阶段的 Hooks 调用通常涉及到比较前后的状态或 props,以确定是否需要执行某些操作或副作用。
  
为什么需要不同的调度器实例?
- 性能优化:通过在不同的渲染阶段使用不同的调度器实例,React 可以更精确地控制 Hooks 的行为,从而优化性能。
- 避免副作用的重复执行:在更新阶段,React 需要区分哪些副作用需要重新执行,哪些可以保持不变。
- 保持渲染的一致性:确保组件的渲染行为在不同的渲染阶段保持一致性。
useState解析
useState解析-mountState
mountState就是useState的实现,间接调用了mountStateImpl、mountWorkInProgressHook。下面展开详细解读
mountWorkInProgressHook
- 拿到当前FiberNode的workInProgressHook变量(可以将其理解为hooks链表的指针),将其指向当前最新hook,并返回引用。
- currentlyRenderingFiber.memoizedState指向hooks链表的头指针。
function mountWorkInProgressHook(): Hook {
   
  const hook: Hook = {
   
    memoizedState: null,
    baseState: null,
    baseQueue: null,
    queue: null,
    next: null,
  };
  if (workInProgressHook === null) {
   
    // This is the first hook in the list
    currentlyRenderingFiber.memoizedState = workInProgressHook = hook;
  } else {
   
    // Append to the end of the list
    workInProgressHook = workInProgressHook.next = hook;
  }
  return workInProgressHook;
}
通过调用,先将hook挂在到filber node的hooks链表上
 计算传入的初始值,并赋值给hook.memoizedState
 给hook.queue 赋初值。创建一个新的链表作为更新队列,用来存放更新(setXxx())
function mountStateImpl<S>(initialState: (() => S) | S): Hook {
   
  const hook = mountWorkInProgressHook();
  if (typeof initialState === 'function') {
   
    const initialStateInitializer = initialState;
    // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
    initialState = initialStateInitializer();
    if (shouldDoubleInvokeUserFnsInHooksDEV) {
      setIsStrictModeForDevtools(true);
      // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
      initialStateInitializer();
      setIsStrictModeForDevtools(false);
    }
  }
  hook.memoizedState = hook.baseState = initialState;
  const queue: UpdateQueue<S, BasicStateAction<S>> = {
   
    pending: null,
    lanes: NoLanes,
    dispatch: null,
    lastRenderedReducer: basicStateReducer,
    lastRenderedState: (initialState: any),
  };
  hook.queue = queue;
  return hook;
}
创建一个 dispatch 示例方法(即 useState 返回的数组的第二个参数:setXxx()),
 该方法的作用是用来修改 state,并将此更新添加到更新队列中,通过 .bind 把当前 fiber node、更新队列、 dispatch 方法关联起来:
function mountState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
   
  const hook = mountStateImpl(initialState);
  const queue = hook.queue;
  const dispatch: Dispatch<BasicStateAction<S>> = (dispatchSetState.bind(
    null,
    currentlyRenderingFiber,
    queue,
  ): any);
  queue.dispatch = dispatch;
  return [hook.memoizedState, dispatch];
}
综上,useState 在 Mount (组件初始化)阶段:
- 获取当前 Hook 节点,同时将当前 Hook 添加到 Hook 链表中
- 初始化 Hook 的状态,即读取初始 state 值
- 创建一个新的链表作为更新队列,用来存放更新操作setXxx(),













![[数据集][目标检测]电力场景输电线异物检测数据集VOC+YOLO格式2060张1类别](https://i-blog.csdnimg.cn/direct/087fcbb6be024598bf6ab04a9457483d.png)




