facebook/reactMITd083ec1Report / request removal

Render Phase

The render phase builds a work-in-progress Fiber tree without immediately applying the resulting host mutations. Its two central operations are beginWork, which evaluates a Fiber and reconciles its children, and completeWork, which finalizes a Fiber after its descendants are processed.

This separation exists so React can prepare, abandon, retry, or defer work before the host tree is changed. Render-time paths can explicitly interrupt work—for example, selective hydration schedules another attempt and throws SelectiveHydrationException—while host updates are recorded for later commit handling.

Sources: packages/react-reconciler/src/ReactFiberBeginWork.js:4223-4509, packages/react-reconciler/src/ReactFiberCompleteWork.js:1082-2112, packages/react-reconciler/src/ReactFiberBeginWork.js:982-1061, packages/react-reconciler/src/ReactFiberCompleteWork.js:674-684

Core concepts

Begin phase

The begin phase decides what a Fiber should render next, evaluates component logic, and creates or reconciles its child Fibers through beginWork.

Sources: packages/react-reconciler/src/ReactFiberBeginWork.js:4223-4509

Complete phase

The complete phase closes a Fiber after its children are processed, restores stack context, prepares host instances, and bubbles flags and lanes upward through completeWork.

Sources: packages/react-reconciler/src/ReactFiberCompleteWork.js:1082-2112, packages/react-reconciler/src/ReactFiberCompleteWork.js:793-914

Work-in-progress tree

The work-in-progress tree is the temporary Fiber structure whose pending props, children, lanes, and flags are changed while a render is being prepared.

Sources: packages/react-reconciler/src/ReactFiberBeginWork.js:4223-4509, packages/react-reconciler/src/ReactFiberWorkLoop.js:3103-3122

Bailout

A bailout skips evaluating a Fiber when neither it nor its relevant subtree has work, while still preserving the bookkeeping needed for context, lanes, and traversal.

Sources: packages/react-reconciler/src/ReactFiberBeginWork.js:3823-3862

How beginWork builds the next tree

beginWork receives the current Fiber, its work-in-progress counterpart, and the render lanes. It first compares old and new props, legacy context, and scheduled work; when nothing relevant changed, it can take an early bailout instead of evaluating the component.

Before dispatching by Fiber tag, beginWork clears the pending lanes on the work-in-progress Fiber. It then selects a tag-specific updater such as updateFunctionComponent, updateClassComponent, updateHostComponent, updateSuspenseComponent, or updateContextProvider.

For a function component, the updater prepares context, calls renderWithHooks, records whether the component performed work, and passes the returned children to reconcileChildren. The return value is the first child Fiber, so the traversal descends into the newly reconciled subtree.

reconcileChildren has separate mount and update paths. A new Fiber mounts children with mountChildFibers; an existing Fiber reconciles against current.child with reconcileChildFibers, producing the next child set for the work-in-progress tree.

The same pattern applies to host components: updateHostComponent establishes host context, determines whether children can be represented as direct text, marks ref work when needed, reconciles children, and returns the first child. A host text Fiber is terminal and returns null, which immediately sends traversal to completion.

Bailouts do not necessarily discard the subtree. If the Fiber itself has no work but its children do, bailoutOnAlreadyFinishedWork clones the child Fibers and continues with the child; if neither the Fiber nor its children have work, it returns null.

Sources: packages/react-reconciler/src/ReactFiberBeginWork.js:4223-4279, packages/react-reconciler/src/ReactFiberBeginWork.js:4312-4323, packages/react-reconciler/src/ReactFiberBeginWork.js:4223-4509, packages/react-reconciler/src/ReactFiberBeginWork.js:1509-1558, packages/react-reconciler/src/ReactFiberBeginWork.js:338-369, packages/react-reconciler/src/ReactFiberBeginWork.js:1963-2029, packages/react-reconciler/src/ReactFiberBeginWork.js:2101-2107, packages/react-reconciler/src/ReactFiberBeginWork.js:3823-3862

How completeWork closes the subtree

When beginWork returns no next child, the work loop enters completion for that unit. The work loop invokes completeWork, and if completion produces more work it continues there; otherwise it obtains the completed Fiber’s sibling for the next traversal step.

For ordinary function-like Fibers, completeWork pops tree context, calls bubbleProperties, and returns null. Class Fibers additionally pop legacy context before bubbling. This is the complementary responsibility to beginWork: the begin phase chooses children, while the complete phase closes the Fiber and summarizes descendant work.

bubbleProperties walks the completed Fiber’s children and combines their lanes, subtree flags, and—when profiling is enabled—duration data. It also repairs each child’s return pointer in the normal non-bailout path, preserving the parent links needed by later traversal and scheduling.

Host completion prepares the renderer-facing result. For a mutating renderer, updateHostComponent compares old and new props and marks the Fiber with Update when they differ; for persistent renderers, it may clone the instance, rebuild child sets, and append terminal host children.

Host text follows the same separation. If text changes in mutation mode, updateHostText only marks the Fiber with Update; the excerpt explicitly states that the actual work is done in commitWork.

function markUpdate(workInProgress: Fiber) {
  workInProgress.flags |= Update;
}

markUpdate records an update flag rather than mutating the host tree immediately.

The traversal itself is a depth-first walk down through child pointers and back up through return and sibling pointers. appendAllChildren demonstrates the same shape: descend when a node has a child, then climb through return until a sibling is available, stopping at the completed parent.

The render-phase call order can be summarized as follows.

Render traversal — How does rendering walk down and back up the Fiber tree?

Evidence

Sources: packages/react-reconciler/src/ReactFiberWorkLoop.js:3388-3414, packages/react-reconciler/src/ReactFiberCompleteWork.js:1082-1117, packages/react-reconciler/src/ReactFiberCompleteWork.js:793-856, packages/react-reconciler/src/ReactFiberCompleteWork.js:463-549, packages/react-reconciler/src/ReactFiberCompleteWork.js:674-684, packages/react-reconciler/src/ReactFiberCompleteWork.js:201-203, packages/react-reconciler/src/ReactFiberCompleteWork.js:245-287

Why render can be interrupted

Render work is interruptible because the reconciler is constructing and annotating a separate work-in-progress result rather than applying every host change as it evaluates components. Host completion records mutations with flags, and selective hydration can schedule a higher-priority retry before throwing SelectiveHydrationException to stop the current render.

Suspense and Offscreen paths also make interruption explicit. A hidden Offscreen subtree can save its base lanes and cache pool, preserve stack symmetry, propagate needed context, and return null so the subtree can resume later.

A render may therefore be abandoned or replayed without requiring the host tree to reflect a partially evaluated component tree. Suspended function components have a dedicated replay path that reuses hooks from the previous attempt, then either bails out or reconciles children again.

The commit boundary is different: the render phase prepares flags and host instances, while commitWork performs the host-side work for flagged updates. The separation prevents a partially completed render from being mistaken for a completed host update; interruption is handled before those commit-side effects are applied.

Sources: packages/react-reconciler/src/ReactFiberCompleteWork.js:674-684, packages/react-reconciler/src/ReactFiberBeginWork.js:1036-1061, packages/react-reconciler/src/ReactFiberBeginWork.js:833-876, packages/react-reconciler/src/ReactFiberBeginWork.js:1561-1601

How it connects

beginWork is driven by the reconciler work loop and therefore connects directly to Work Loop & Scheduling, which supplies the render lanes and invokes the begin and complete operations.

The child creation performed by reconcileChildren is the entry point to Reconciliation Algorithm, where matching, mounting, deletion, and key handling determine the next child Fibers.

The temporary Fiber structure and its current/work-in-progress relationship are described in Fiber Architecture. Bailouts reuse dependencies, child lanes, and cloned child Fibers within that double-buffered structure.

Flags prepared during completion are consumed by Commit Phase, while host-specific instance creation and updates are supplied by ReactDOM Host Config.

Sources: packages/react-reconciler/src/ReactFiberWorkLoop.js:3103-3122, packages/react-reconciler/src/ReactFiberBeginWork.js:338-369, packages/react-reconciler/src/ReactFiberBeginWork.js:3823-3862, packages/react-reconciler/src/ReactFiberCompleteWork.js:463-549, packages/react-reconciler/src/ReactFiberCompleteWork.js:674-684

Key takeaways

  • beginWork evaluates a Fiber and reconciles its children; completeWork closes the Fiber, prepares host results, and bubbles subtree data.
  • The walk descends through child Fibers during begin work and returns through completion, siblings, and parent pointers.
  • Bailouts skip unchanged work but continue into child subtrees when their lanes still contain pending work.
  • Render records flags such as Update; host mutation work is deferred to commit handling.
  • Suspension, Offscreen deferral, and selective hydration provide explicit interruption and retry paths.

Sources: packages/react-reconciler/src/ReactFiberBeginWork.js:4223-4509, packages/react-reconciler/src/ReactFiberCompleteWork.js:1082-2112, packages/react-reconciler/src/ReactFiberWorkLoop.js:3103-3122, packages/react-reconciler/src/ReactFiberCompleteWork.js:245-287, packages/react-reconciler/src/ReactFiberBeginWork.js:3823-3862, packages/react-reconciler/src/ReactFiberCompleteWork.js:201-203, packages/react-reconciler/src/ReactFiberCompleteWork.js:674-684, packages/react-reconciler/src/ReactFiberBeginWork.js:1036-1061

Want this for your repos?

Try Angada AI Wiki