Skip to main content

Article · React Fiber Internals · Part 1

React Fiber: How the Tree Walk and Work Loop Actually Run

Fiber walks units of work depth-first, can pause between units, and only finishes a tree when the work loop completes without higher-priority interruption.

Author
Mohammed Abdelhady
Published
Updated
Reading time
14 min read
Abstract fiber tree with an orange route tracing the depth-first traversal between nodes
A project-owned visual metaphor for React's depth-first fiber tree walk.

Opening answer

React Fiber does not re-render your whole app as one uninterruptible call stack. It turns the component tree into a linked graph of fiber nodes (units of work), then walks that graph in a work loop: take a unit, process it, choose the next unit, and optionally yield so the browser can paint or handle input before continuing.

If you only remember one sentence: the tree walk builds a work-in-progress fiber tree; the work loop decides when that walk may pause; commit is a later phase.

What a fiber is

A fiber is React’s internal unit of work for one component (or host node). Conceptually it stores:

  • which element type and props are being processed
  • links to parent, sibling, and child fibers
  • alternate pointer between current and work-in-progress trees
  • effect flags describing what must happen at commit

Public React docs describe rendering as preparing the next UI and committing as applying it to the DOM. Fiber is the reconciler’s data structure that makes those phases schedulable rather than a single deep recursive call.

See Render and Commit for the product-level phases this model implements.

The tree walk shape

Traversal is effectively depth-first:

  1. Begin work on a fiber (process the component function or host update path).
  2. If children are produced, descend into the child.
  3. When a subtree completes, move to the sibling.
  4. When no sibling remains, complete the parent and bubble up.

That “complete” step is where React finalizes the unit and records side effects for later commit. It is still render-phase work: pure preparation, not DOM mutation.

Scroll horizontally to explore this diagram.

Conceptual fiber tree labeled App, Header, Main, List, and Footer. Numbered solid arrows descend through child links or advance through sibling links after Header and List complete. Dashed arrows show the final Footer branch climbing its return links to Main and then App.
Traversal follows fiber links. Begin work descends to a child; after Header or List completes, the walk advances to its sibling. Only the final Footer branch climbs its return links through Main to App. React may yield between units, but host changes wait for commit.

In other words, a fiber’s child link descends one level, sibling advances at the same level after that unit completes, and return climbs only when no sibling remains. The numbered route shows App → Header → Main → List → Footer; the dashed route starts at Footer and completes Main → App. Neither route mutates the DOM during render.

A minimal mental model

Imagine this element tree:

App
├─ Header
└─ Main
   ├─ List
   └─ Footer

A simplified walk order for begin-work is roughly: App → Header → (complete Header) → Main → List → (complete List) → Footer → (complete Footer) → (complete Main) → (complete App).

The exact internal function names change across React versions. Prefer conceptual claims tied to documented phases over version-locked folklore from old blog posts.

The work loop

The work loop repeatedly:

  1. Picks the next unit of work (the next fiber to process).
  2. Performs begin/complete work for that unit.
  3. Checks whether time remains in the current frame / lane budget.
  4. Either continues or yields, scheduling a continuation.

Yielding is why Fiber can keep the UI responsive under concurrent features: work between units is interruptible; commit remains carefully ordered and, for DOM mutations, deliberately short.

Concurrent features and lane priorities are covered in Part 2. This part only needs the loop idea: progress is a sequence of units, not one recursive mount.

What yielding does and does not mean

Yielding does not mean React randomly abandons correctness. It means:

  • React may stop after finishing a unit of work.
  • Higher-priority updates can cause the work-in-progress tree to be restarted or rebased depending on the update model.
  • Until commit, users still see the previous committed UI.

State during render still behaves as a snapshot of values for that render, which is why render must stay free of irreversible side effects. See State as a Snapshot.

Caveats that matter in production

  • Do not put DOM writes or subscriptions in render. They belong in effects or event handlers. Interruptible render makes this a correctness issue, not just style.
  • Implementation details move. Public docs and the react-reconciler package are safer anchors than screenshots of internal variables from a random year.
  • Profiling beats folklore. When something feels “slow,” measure with React Profiler and browser performance tools before blaming “the fiber loop.”

Why this model exists

The stack reconciler React used historically walked the tree as a recursive function call. Deep trees and large updates blocked the main thread until the walk finished. Fiber reifies the stack into a heap-allocated graph so React can:

  • pause and resume work
  • assign priority to updates
  • keep a current tree while preparing a work-in-progress tree

That architectural shift is the foundation for concurrent rendering. You do not need every internal constant to use React well—but understanding units of work prevents wrong mental models like “setState always rebuilds everything synchronously end-to-end.”

Practical takeaways for day-to-day React

  1. Keep render pure. Treat it as computing the next UI description.
  2. Split expensive pure work with memoization only when measured; Fiber helps scheduling, it does not remove your O(n) cost inside a component body.
  3. Prefer concurrent-friendly patterns (startTransition for non-urgent updates) once you understand that urgent and non-urgent work compete for the same loop.
  4. Read commit as a separate phase. Layout and passive effects run after the tree is committed—not inside the walk itself.

Takeaway

Fiber’s tree walk turns components into linked units of work. The work loop processes those units with optional yielding so React can stay interruptible before a carefully ordered commit. Once that model is solid, buffers, hooks, lanes, and commit explain how priorities and hook state ride on top of the same graph.

Further reading