DEV Community

Yogesh Bamanier
Yogesh Bamanier

Posted on

๐Ÿš€ Demystifying React Fiber: A Guide to Incremental & Concurrent Rendering โš›๏ธ

An in-depth guide on React Fiber, exploring WIP, commit phase, incremental and concurrent rendering, multiple WIP trees, and hooks management.


๐ŸŒŸ Introduction

When I started digging into React Fiber, I had endless questions swirling in my head:

  • When is the WIP (work-in-progress) Fiber created?
  • If a childโ€™s state updates, why does React rebuild from the parent?
  • What happens if half of the work is done and React decides to pause?
  • Can multiple WIP trees exist at the same time?

This article is a knowledge base + story of my journey understanding Fiber. Iโ€™ll explain concepts in sequence while weaving in the exact questions that drove my curiosity.


๐Ÿงต The First Spark โ€” When is Fiber Created?

When you run:

import { createRoot } from "react-dom/client"; createRoot(container).render(<App />); 
Enter fullscreen mode Exit fullscreen mode
  • React creates a Root Fiber (HostRootFiber).
  • From this root, React builds the current Fiber tree (the DOM your app shows).
  • At the same time, whenever a render is triggered, React starts building a WIP Fiber tree (the potential next UI).

๐Ÿ‘‰ Only one root Fiber exists, but it can have two children:

  • current โ†’ whatโ€™s painted on screen.
  • workInProgress โ†’ being built in memory for the next paint.

๐Ÿ”„ The WIP Story

My Question:

Does React build WIP after each commit? If yes, how does it know about pending work?

Answer:

  • After every commit, the WIP becomes the new current.
  • If updates are queued while rendering, React either:

    • Reuses partial WIP work (resume rendering).
    • Discards half-done WIP and starts a fresh one for better responsiveness.

๐Ÿ’ก Even if React discards a WIP, your updates arenโ€™t lost โ€” they live in the update queue of the current Fiber.


โธ๏ธ Pausing, Resuming, and Discarding

React Fiber was built to support interruptible rendering.

  • If work takes too long, React will yield (pause) to let the browser paint.
  • On the next frame, React can:

    • Resume the same WIP (continue where it left).
    • Discard WIP and rebuild from current (if higher-priority update arrived).

๐Ÿ“Œ Example:
If you typed into <input />, React might throw away half-done WIP and rebuild quickly so your keystroke feels instant.


๐ŸŒณ Parentโ€“Child Fiber Reconciliation

My Question:

If only child1 state changes, why does React traverse from root โ†’ parent โ†’ child1 โ†’ child2?

Answer:

Because reconciliation always starts from the parent of the updated Fiber.

  • Parentโ€™s WIP Fiber is rebuilt.
  • Children are visited to decide:

    • Reuse existing Fiber (alternate).
    • Or create new WIP Fiber (if props/state changed).

๐Ÿ‘‰ This is why even siblings (like child2) may be traversed, though not always rebuilt.


โšก Commit Phase โ€” Expanded View

I initially thought commit = โ€œDOM changes are appliedโ€, but itโ€™s much richer.

Commit has three steps:

  1. Before Mutation (snapshot phase)
  • getSnapshotBeforeUpdate
  • React prepares, e.g., measuring scroll position.
  1. Mutation Phase (sync, cannot be interrupted ๐Ÿšจ)
  • DOM nodes are created/updated/removed.
  • Example: inserting all ready child DOM nodes in a single batch for performance.
  1. Layout Phase (effects)
  • Runs lifecycle hooks:

    • componentDidMount
    • componentDidUpdate
  • Runs passive effects scheduling.

๐Ÿ‘‰ Only after this, the browser paints with the new UI.


๐ŸŽญ Multiple WIP Trees

Hereโ€™s the part that really blew my mind:

  • React can prepare multiple versions of the UI simultaneously, but only in between commit waves.
  • At any given moment:

    • current โ†’ the UI you see.
    • One or more WIP candidates in memory.

โš–๏ธ React chooses the winning WIP at commit time. Others are discarded.

๐Ÿ“Œ Example Flow:

  • Frame 1: WIP Slice A (30 Fibers). Yield.
  • Frame 2: Higher-priority update arrives. React may abandon Slice A.
  • Frame 3: New WIP tree built, committed, and painted.

So yes โ€” multiple WIPs can exist between commits, but only one reaches the DOM.


๐Ÿงฉ Incremental Rendering vs Concurrent Rendering

I used to mix these two. Hereโ€™s the difference:

Incremental Rendering (Time Slicing)

  • Breaks a single render into smaller chunks (slices)
  • Each slice is executed for a small duration (~5ms-16ms), then yields control to the browser
  • Keeps the UI responsive during heavy renders

Example:

function App() { return ( <> <HeavyList /> // takes long to render <Sidebar /> // light component </> ); } 
Enter fullscreen mode Exit fullscreen mode
  • React renders Sidebar in the first slice, then starts HeavyList
  • If a user clicks a button during HeavyList rendering, React can yield to handle input immediately

Concurrent Rendering

  • React can prepare multiple WIP trees simultaneously for the same root
  • Enables high-priority updates to interrupt low-priority work
  • WIP trees are in memory; only one is committed to the DOM

Example:

<App> <SearchBar /> // high priority <Feed /> // low priority, heavy list </App> 
Enter fullscreen mode Exit fullscreen mode
  • Typing in SearchBar triggers a high-priority WIP tree
  • React may pause Feed WIP, build SearchBar update concurrently
  • The most appropriate WIP tree commits first

Key Difference:

  • Incremental = split one render into chunks
  • Concurrent = multiple possible renders at the same time, React decides which to commit

๐Ÿ•’ Timeline Comparison

Incremental Rendering

Type "a" -> Render Input Fiber -> Pause -> Render List Fiber (chunked) -> Commit everything 
Enter fullscreen mode Exit fullscreen mode

Concurrent Rendering

Type "a" -> Commit Input Fiber immediately -> Start List Fiber in background Type "ab" before List finishes -> Discard old List Fiber -> Start new List Fiber with "ab" -> Commit when ready 
Enter fullscreen mode Exit fullscreen mode

This timeline shows how incremental rendering splits work in one render while concurrent rendering handles multiple WIPs and high-priority interruptions.


๐Ÿ“– Key Takeaways

  • Fiber enables time-sliced, interruptible rendering.
  • WIP is always built in memory; DOM only updates during commit.
  • React may pause, resume, or discard WIP based on priority.
  • Multiple WIP trees can exist between commit waves, but only one survives.
  • Commit Phase has 3 sub-phases (before mutation, mutation, layout).
  • Update queues ensure no user input is lost, even if WIP is thrown away.

โœ๏ธ Author

๐Ÿ‘จโ€๐Ÿ’ป Yogesh Bamanier
๐Ÿ”— LinkedIn

Top comments (0)