⚠️ React@18.2.0을 기반으로 작성되었으며, 최신 버전에서는 구현이 변경되었을 수 있습니다.
renderRootSync()
root.current
: FiberNode
— 비어있는 Fiber 트리 (child
: null
)
root.current.alternate
: null
1.1 Initial mount —
renderRootSync()
prepareFreshStack()
root.current.alternate
: FiberNode
— 비어있는 Fiber 트리 생성!
1.2 Initial mount —
prepareFreshStack()
performConcurrentWorkOnRoot()
root.current.alternate
: FiberNode
— Fiber 트리 완성!
1.3 Initial mount —
performConcurrentWorkOnRoot()
(1)
root.current
: FiberNode
— 여전히 비어있는 Fiber 트리
1.3 Initial mount —
performConcurrentWorkOnRoot()
(2)
commitRoot()
root.current
업데이트 및 화면에 commit 완료!
⇒ workInProgress였던 root.current.alternate
과, root.current
가 가리키는 트리 서로 switch!
출처: https://jser.dev/2023-07-14-initial-mount/#5-summary
root.current
: FiberNode
— root.current.alternate
가 만든 Fiber 트리 포인트!
1.4 Initial mount —
commitRoot()
(1)
root.current.alternate
: FiberNode
— root.current
가 가리켰던 비어있는 Fiber 트리 포인트!
1.4 Initial mount —
commitRoot()
(2)
renderRootSync()
root.current
: FiberNode
— initial mount에서 완성한 Fiber 트리
root.current.alternate
: FiberNode
— 비어있는 Fiber 트리 (child
: null
)
2.1 Re-render —
renderRootSync()
prepareFreshStack()
root.current.alternate
: FiberNode
— root.current
와 같은 모양의 Fiber 트리로 업데이트!
Cf. prepareFreshStack()
에서 호출하는 createWorkInProgress()
에서 root.current
트리 복사!
💻 src: ReactFiber.js - createWorkInProgress()
export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber { let workInProgress = current.alternate; if (workInProgress === null) { // We use a double buffering pooling technique because we know that we'll // only ever need at most two versions of a tree. We pool the "other" unused // node that we're free to reuse. This is lazily created to avoid allocating // extra objects for things that are never updated. It also allow us to // reclaim the extra memory if needed. workInProgress = createFiber( current.tag, pendingProps, current.key, current.mode, ); workInProgress.elementType = current.elementType; workInProgress.type = current.type; workInProgress.stateNode = current.stateNode; workInProgress.alternate = current; current.alternate = workInProgress; } else { workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. workInProgress.type = current.type; // We already have an alternate. // Reset the effect tag. workInProgress.flags = NoFlags; // The effects are no longer valid. workInProgress.subtreeFlags = NoFlags; workInProgress.deletions = null; // Reset all effects except static ones. // Static effects are not specific to a render. workInProgress.flags = current.flags & StaticMask; workInProgress.childLanes = current.childLanes; workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so // it cannot be shared with the current fiber. const currentDependencies = current.dependencies; workInProgress.dependencies = currentDependencies === null ? null : { lanes: currentDependencies.lanes, firstContext: currentDependencies.firstContext, }; // These will be overridden during the parent's reconciliation workInProgress.sibling = current.sibling; workInProgress.index = current.index; workInProgress.ref = current.ref; workInProgress.refCleanup = current.refCleanup; return workInProgress; }
2.2 Re-render —
prepareFreshStack()
performConcurrentWorkOnRoot()
root.current.alternate
: FiberNode
— 트리에 Effect 반영 (e.g. TextNode 0 → 1)
2.3 Re-render —
performConcurrentWorkOnRoot()
(1)
root.current
: FiberNode
— initial mount에서 완성한 Fiber 트리 그대로
2.3 Re-render —
performConcurrentWorkOnRoot()
(2)
commitRoot()
root.current
업데이트 및 화면에 commit 완료!
⇒ workInProgress였던 root.current.alternate
과, root.current
가 가리키는 트리 서로 switch!
2.4 Re-render —
commitRoot()
(1)
root.current.alternate
: FiberNode
— root.current
가 가리켰던 Fiber 트리 포인트!
2.4 Re-render —
commitRoot()
(2)