Skip to main content
React’s Fiber architecture is a complete rewrite of the reconciliation algorithm that enables concurrent rendering and fine-grained control over the rendering process.

Work loop and unit of work

The Fiber reconciler operates on a work loop that processes units of work incrementally. This allows React to break rendering work into chunks and spread it across multiple frames.
The work loop is the heart of React’s concurrent rendering capabilities. Each iteration processes a single “unit of work” - a Fiber node representing a component or DOM element.

How the work loop operates

1

Pick next unit of work

The scheduler selects the next Fiber node to process based on priority levels and available time.
2

Perform work

React calls beginWork to process the Fiber node, which may create child Fibers, update state, or compute new props.
3

Check for interruption

After each unit of work, React checks if it needs to yield to the browser for high-priority tasks like user input.
4

Continue or yield

If time remains in the current frame, continue to the next unit of work. Otherwise, yield control back to the browser.
Each unit of work represents a Fiber node in the component tree. The work loop traverses this tree depth-first, processing each node and its children.
Called when starting to process a Fiber node. This function:
  • Compares old and new props
  • Calls render methods or function components
  • Creates child Fiber nodes
  • Returns the next unit of work (first child)

Reconciliation phases

React’s reconciliation process is split into two distinct phases to enable work interruption and prioritization.

Render phase

The render phase is interruptible and produces a list of changes without mutating the DOM.
The render phase can be interrupted, aborted, or restarted. This is why side effects should never be placed in render methods.
During the render phase, React:
  • Walks the Fiber tree
  • Computes differences between current and new state
  • Marks Fibers with effects (updates, deletions, insertions)
  • Builds the effect list
  • Can be paused and resumed

Commit phase

The commit phase is synchronous and uninterruptible. It applies all the changes to the DOM in one go.
1

Before mutation

React calls getSnapshotBeforeUpdate lifecycle method and schedules effect cleanup functions.
2

Mutation

React applies all DOM mutations, insertions, deletions, and updates. This is when the DOM actually changes.
3

Layout effects

React calls useLayoutEffect hooks and componentDidMount/componentDidUpdate lifecycle methods. These run synchronously before the browser paints.
4

Passive effects

React schedules useEffect hooks to run asynchronously after the paint.
  • Interruptible: Can be paused and resumed
  • No side effects: Pure computation only
  • No DOM changes: Works with Fiber tree in memory
  • Can be restarted: Higher priority work can interrupt

Effect list construction

As React traverses the Fiber tree during the render phase, it constructs a linear list of Fibers that have side effects.
The effect list is an optimization that allows React to skip Fiber nodes without effects during the commit phase, making commits much faster.
The effect list is a linked list containing only Fibers that need work in the commit phase:
  • Component updates
  • DOM insertions
  • DOM deletions
  • Ref updates
  • Effect hook callbacks
Instead of traversing the entire Fiber tree again during commit, React only walks the effect list. For large trees with few changes, this can be dramatically faster.

Effect tags

Each Fiber in the effect list has effect tags that describe what work needs to be done:
A new Fiber that needs to be inserted into the DOM.

Priority levels and lane model

React uses a sophisticated priority system called “lanes” to manage concurrent work and ensure the most important updates happen first.

Priority levels

Different types of updates have different priority levels:
1

Immediate/Sync

Discrete user input like clicks and key presses. Must be processed immediately to feel responsive.
2

User-blocking

Continuous user input like hover or scroll. Should complete quickly but can tolerate slight delays.
3

Normal

Network responses, animations not triggered by user input. Default priority for most updates.
4

Low

Updates that can be deferred, like analytics or logging.
5

Idle

Work that only happens when the browser is idle, like offscreen rendering.

Lane model

React’s lane model uses a bitmask system where each “lane” represents a priority level or category of work.
Lanes are represented as 32-bit integers where each bit represents a lane. This allows React to efficiently check for overlapping priorities using bitwise operations.
The lane model provides several advantages:
A single render can include updates from multiple priority levels. Lanes make it easy to track and manage these mixed priorities.
When a state update occurs, React assigns it to a lane based on its priority. During the render phase, React processes lanes from highest to lowest priority, interrupting lower-priority work when higher-priority updates arrive.
The lane model is what enables React’s concurrent features like useTransition and useDeferredValue to mark updates as lower priority while keeping the UI responsive.

Build docs developers (and LLMs) love