Skip to content
Lesson 6 of 14

Step 1 of 5 · Reading · ~4 min

Read

Virtual DOM & Diffing

The Reconciler Loop

The diff of lesson 5 compares trees. The reconciler is the loop around it: it remembers the last tree, decides what survives a render and what is torn down, and decides when a render happens at all. After this lesson your program tracks mounted component instances across renders, with their state, and batches updates.

What the loop keeps

Between renders the reconciler holds the previous tree, and attached to each component in it an instance: the component's state, its effects, its place in the tree. Render only decides what the screen should look like. Whether a component keeps its state across the next render depends on one question: is the new element the same instance as the old one?

Without keys the answer uses the two heuristics from lesson 5: same position, same type.

At this positionResult
old type equals new typethe instance survives; it is re-rendered with its state intact
old type differs from new typethe old instance is unmounted and its state destroyed; a new one mounts with fresh state
only an old elementit unmounts
only a new elementit mounts

This is the rule people trip over. Render [A, B] and click inside A three times. Render [A, C]: A still shows 3, B is gone, C starts from zero. Now render [B, A] instead of [A, B]: position 0 changed from A to B, so both instances are destroyed and rebuilt, even though the same two components are on screen. Position, not content, is identity. Lesson 8 gives you a way to say otherwise.

Scheduling, not calling

A naive state setter re-renders immediately, so a handler that updates three pieces of state renders three times, and the first two renders show a half-updated screen. Real frameworks only mark the instance dirty and schedule one render for later. Many writes, one render:

click, click, click      count goes 0 to 3 and the instance is marked dirty (once)
end of the event         flush: re-render each dirty instance once, showing count=3

Two refinements fall out of that. A component that is dirty when its parent re-renders needs no second render, because the parent's render already shows its newest state. And if nothing is dirty, the flush does nothing at all.

Render phase and commit phase

Each round has two halves. The render phase builds the new tree and works out what changed; it touches no DOM and may be abandoned, so it must be free of side effects. The commit phase applies the DOM operations and cannot be interrupted. Effects such as useEffect run after commit, never during render. React 16 rewrote the render phase as Fiber, a linked list of work units instead of a recursive walk, which can be paused between units; that is what makes time slicing, concurrent rendering and Suspense possible.

Doing less work

React.memo skips a component whose props are equal, useMemo and useCallback keep values stable so that skip actually happens, and Server Components never enter the client bundle at all. Each of these is a bailout from the loop above; none changes the loop.

The script you will run

RENDER A,B      a parent renders children of types A and B
CLICK 0         the instance at position 0 changes its state (count + 1)
FLUSH           re-render every dirty instance, once

The exercise text lists the exact lines printed for each event.

Common mistakes

  • Matching by type anywhere in the list instead of by position, so [B, A] keeps both instances. That is keyed behaviour, not this lesson's.
  • Keeping state across a type change at the same position.
  • Printing one update per click instead of one per dirty instance per flush.
  • Leaving the dirty flag set on an instance that a parent render just refreshed, so the next flush updates it again.
  • Unmounting after mounting at a changed position. The old instance goes first.

Your exercise

The starter reads the script and applies CLICK. You write reconcile, the matching and lifecycle for a parent render, and flush, the batched update.

Up nextEvent HandlingVirtual DOM & Diffing

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…