Skip to content

useReducer更新源码实现

packages/react-reconciler/src/ReactFiberHooks.js

js
import { scheduleUpdateOnFiber } from "./ReactFiberWorkLoop";
import { enqueueConcurrentHookUpdate } from './ReactFiberConcurrentUpdates';

function dispatchReducerAction(fiber, queue, action) {
    const update = {
      action,
      next: null
    }
    const root = enqueueConcurrentHookUpdate(fiber, queue, update);
    scheduleUpdateOnFiber(root);
}

export function renderWithHooks(current, workInProgress, Component, props) {
  currentlyRenderingFiber = workInProgress;  // 设置当前正在渲染的fiber节点
  if (current !== null && current.memoizedState !== null) {
    ReactCurrentDispatcher.current = HooksDispatcherOnUpdate;
  } else {
    ReactCurrentDispatcher.current = HooksDispatcherOnMount;
  }
  const children = Component(props);  // 通过组件和props渲染子节点
  currentlyRenderingFiber = null;
  workInProgressHook = null;
  currentHook = null;
  return children;  // 返回子节点
}

packages/react-reconciler/src/ReactFiberConcurrentUpdates.js

js
const concurrentQueue = [];
let concurrentQueuesIndex = 0;

function enqueueUpdate(fiber, queue, update) {
  concurrentQueue[concurrentQueuesIndex++] = fiber;
  concurrentQueue[concurrentQueuesIndex++] = queue;
  concurrentQueue[concurrentQueuesIndex++] = update;
}

export function finishQueueingConcurrentUpdates() {
  const endIndex = concurrentQueuesIndex;
  concurrentQueuesIndex = 0;
  let i = 0;
  while (i < endIndex) {
    const fiber = concurrentQueue[i++];
    const queue = concurrentQueue[i++];
    const update = concurrentQueue[i++];
    if (queue !== null && update !== null) {
      const pending = queue.pending;
      if (pending === null) {
        update.next = update;
      } else {
        update.next = pending.next;
        pending.next = update;
      }
      queue.pending = update;
    }
  }
}

packages/react-reconciler/src/ReactFiberWorkLoop.js

js
import { finishQueueingConcurrentUpdates } from './ReactFiberConcurrentUpdates';
function prepareFreshStack(root) {
  workInProgress = createWorkInProgress(root.current, null);
  finishQueueingConcurrentUpdates()
}

基于 VitePress 构建