Article · React Fiber Internals · Part 2
React Fiber: Buffers, Hooks, Lanes, and Commit
Work-in-progress buffers hold the next tree, hooks store state on fibers, lanes prioritize updates, and commit applies the finished tree in a short, ordered phase.
- Author
- Mohammed Abdelhady
- Published
- Updated
- Reading time
- 16 min read

Table of contents
Opening answer
After the tree walk and work loop prepare updates, four ideas complete the picture:
- Buffers — React keeps a current fiber tree (what is on screen) and a work-in-progress tree (what is being prepared).
- Hooks — hook state and queues live on the fiber for that component instance, not in your function closure permanently.
- Lanes — updates carry priority bands so urgent work can outrank non-urgent work.
- Commit — once a tree is finished, React applies DOM/host changes and runs effects in a structured phase.
Current vs work-in-progress buffers
Double buffering is the core design:
- Current tree — last committed UI description.
- Work-in-progress (WIP) tree — alternate fibers being built by the work loop.
Fibers point at their alternates. When commit succeeds, the WIP tree becomes current. This is why render can be thrown away under concurrency without corrupting the visible UI: incomplete WIP work is discarded or restarted; the current tree remains stable until a successful commit.
Product-level documentation groups this under render vs commit in Render and Commit.
Where hooks attach
Hooks are not free-floating globals. For a function component fiber, React stores a linked list (or equivalent structure) of hook cells:
- state value and update queue for
useState/useReducer - memoized values for
useMemo/useCallback - effect lists for
useEffect/useLayoutEffect - refs for
useRef
Rules of Hooks exist because the order of hook calls must match the order of cells on that fiber. Conditional hooks break the cell alignment and produce incorrect state pairing.
Update queues
Calling setState does not mutate the screen immediately. It queues an update associated with that hook cell and schedules work on the fiber. Multiple updates may be processed together; React’s public guidance covers batching and queueing in Queueing a Series of State Updates.
A practical consequence: logging state immediately after setState still shows the previous snapshot for that render, which matches the “state as a snapshot” model from Part 1.
Lanes and priority (conceptual)
Lanes are React’s internal priority representation for updates. You rarely name a lane in application code. You do choose urgency with APIs such as:
- normal event-driven updates (typically urgent)
startTransitionfor non-urgent UI transitions- deferred values for keeping inputs snappy while heavy UI catches up
Mentally model lanes as: which updates may interrupt or outrank which other updates on the same work loop. Exact bitmasks and lane constants are implementation details and change; public transition APIs are the stable contract.
What not to claim
- Do not assert fixed millisecond budgets for lanes without measuring a specific React version and host environment.
- Do not treat “concurrent mode” as a single boolean switch in modern React; concurrent features are integrated and opt-in via APIs.
- Do not promise that transitions remove all jank—large pure work in render still costs CPU.
Commit phase structure
When the work loop finishes a root, commit applies the prepared tree. Conceptually it includes:
- Before mutation / snapshot work (where applicable)
- Host mutation — DOM inserts, updates, deletes
- Current-tree switch — after mutation and before layout work, the finished WIP tree becomes
root.current - Layout effects —
useLayoutEffectobserves the newly installed tree after DOM updates
Passive effects are scheduled as separate post-commit work. useEffect is for synchronizing with external systems after render, but its timing relative to browser paint can vary with the interaction and scheduler. It is not a second render API and should not be used to compute derived state that could be calculated during render.
Failure isolation mental model
- Errors during render of WIP work can abort that attempt without committing a partial tree.
- Errors during effects have different boundaries (error boundaries catch render; effect errors need careful handling).
- Commit is intentionally shorter and more structured than the potentially long render walk.
Connecting hooks, lanes, and commit
A typical update path:
- Event or transition schedules an update with a priority.
- Work loop renders fibers, reading hook cells and applying queued updates.
- Children reconcile; effect lists accumulate on fibers.
- Commit mutates the host tree, installs the finished tree as current, and runs layout effects; passive effects are scheduled afterward as separate work.
If a higher-priority update arrives during a non-urgent render, React may interrupt the WIP work and prioritize the urgent path. That is why pure render and correct effect placement matter more under concurrency than under the old “always sync” intuition.
Scroll horizontally to explore this diagram.
The boundaries in the figure are the important contract: an update’s urgency influences render scheduling; hook cells and queued updates are read while building the work-in-progress tree; and the visible current tree remains stable until finished work enters commit. Mutation happens before root.current switches to the finished tree, layout effects then observe that installed tree, and passive effects are scheduled outside the synchronous commit sequence. Exact lane bitmasks and internal cell structures remain version-dependent implementation details.
Practical checklist
- Mark non-urgent UI with transitions when typing must stay responsive while a heavy view updates.
- Put DOM measurements in layout effects only when needed; prefer pure layout with CSS when possible.
- Keep external system sync in passive effects and clean up subscriptions.
- Avoid derived state in effects when you can compute during render.
- Measure before micro-optimizing memoization trees.
Takeaway
Buffers separate what users see from what React is preparing. Hooks store state on fibers with ordered cells and queues. Lanes express urgency so the work loop can prefer interactive updates. Commit applies a finished tree and runs effects in a defined order. Together with the tree walk, this is the operational model behind modern React performance APIs—without needing to memorize every internal bit flag.