react/packages/react-reconciler/src at v18.2.0 · facebook/react

React 파이버 아키텍처 분석

Reconcile 단계

root.render() 호출 후 최종적인 렌더 결과물을 알아내귀 위해 재귀적으로 React내의 트리를 탐색하며 기존 뷰와 다른 점을 찾아내는 과정

Reconcile 단계는 크게 beginWorkCompleteWork로 나뉜다.

function performUnitOfWork(unitOfWork: Fiber): void {  
  // The current, flushed, state of this fiber is the alternate. Ideally
  // nothing should rely on this, but relying on it here means that we don't
  // need an additional field on the work in progress.
  const current = unitOfWork.alternate;
  setCurrentDebugFiberInDEV(unitOfWork);

  let next;
  if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {
    startProfilerTimer(unitOfWork);
    next = beginWork(current, unitOfWork, subtreeRenderLanes);
    stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
  } else {
    next = beginWork(current, unitOfWork, subtreeRenderLanes);
  }

  resetCurrentDebugFiberInDEV();
  unitOfWork.memoizedProps = unitOfWork.pendingProps;
  if (next === null) {
    // If this doesn't spawn new work, complete the current work.
    completeUnitOfWork(unitOfWork);
  } else {
    workInProgress = next;
  }

  ReactCurrentOwner.current = null;
}

React 내부에서 루트 FiberNode를 HostRoot 컴포넌트라 부른다는 것을 알 수 있다.

function beginWork(  
  current: Fiber | null,
  workInProgress: Fiber,
  renderLanes: Lanes,
): Fiber | null {
...
    switch (workInProgress.tag) {
    ...
    case HostRoot:
      return updateHostRoot(current, workInProgress, renderLanes);
...
}

HostRoot 컴포넌트 내부를 갱신하는 함수.


function updateHostRoot(current, workInProgress, renderLanes) {  
  pushHostRootContext(workInProgress);

  if (current === null) {
    throw new Error('Should have a current fiber. This is a bug in React.');
  }

  const nextProps = workInProgress.pendingProps;
  const prevState = workInProgress.memoizedState;
  const prevChildren = prevState.element;
  cloneUpdateQueue(current, workInProgress);
  processUpdateQueue(workInProgress, nextProps, null, renderLanes);
...
}

processUpdateQueue()

export function processUpdateQueue<State>(  
  workInProgress: Fiber,
  props: any,
  instance: any,
  renderLanes: Lanes,
): void {
  // This is always non-null on a ClassComponent or HostRoot
  const queue: UpdateQueue<State> = (workInProgress.updateQueue: any);

  hasForceUpdate = false;

진입 이후 컴포넌트는 element필드로 이동.

스크린샷 2024-06-22 오후 3.31.34.png