skip to content

Rendering and Reconciliation

How React turns your components into DOM updates: what schedules a render, how the fiber tree is built and diffed, when the result is committed, and how concurrent rendering can pause the whole thing. Interviewers reach for this area when they want to know whether you can reason about re-render and stale-state bugs instead of guessing.

part ofReactoverview, primer and where to startread it →
on this pageshow

explore

questions

page 2 of 2

React reconciles two element trees in roughly O(n) instead of using a general tree-diff algorithm, which costs about O(n^3). Which assumptions buy that speed, and what does React give up in exchange?

level: middleimportance: should knowfreq 42%

basics

~20 s

React assumes different element types produce different trees, and that keys identify stable children. Those bets replace an O(n^3) comparison with one O(n) pass, at the cost of never reusing a subtree that moved to a new parent.

open as a page

In React, a function component's body runs again from scratch on every render, yet the value returned by useState is still there. Where does React actually keep that state, and what follows from that when the same component is rendered in two places?

level: middleimportance: should knowfreq 45%

basics

~20 s

React stores hook state on the fiber node representing that component instance, as a chain of hook records matched by call order. Every rendered position has its own fiber, so two instances of the same component keep entirely separate state.

open as a page

A React list is rendered with key={crypto.randomUUID()} generated inside the render. What does the reconciler do on every re-render of that list, and why is this worse than keying by array index?

level: middleimportance: should knowfreq 40%

basics

~20 s

Every key is new, so no previous child matches: React deletes every existing fiber and mounts the whole list fresh on each render. Index keys at least pair positionally and reuse most fibers, so they are strictly cheaper.

open as a page

A React component's status state is the string 'idle', and a click handler calls setStatus('idle') again with the identical value. Does React re-render the component, and what comparison decides that?

level: middleimportance: should knowfreq 48%

basics

~20 s

React compares the next state with the current one using Object.is. Because the values match, it bails out and skips re-rendering the subtree — though it may still run this component's function once before bailing out, so never rely on that render not happening.

open as a page

React's render phase visits each node of its work tree twice — once on the way down, in what its source calls beginWork, and once on the way back up, in completeWork. What does React do at each of those two visits, and why is the upward visit needed at all?

level: middleimportance: should knowfreq 32%

basics

~20 s

On the way down, React runs the component and reconciles the elements it returns into child nodes. On the way up, it finishes each node — for host elements it creates the detached DOM instance and appends its finished children — then moves to the sibling or the parent.

open as a page

In a React 19 app, a drag interaction wraps every pointermove state update in `flushSync` so the dragged element keeps up, and the UI now stutters badly. Explain why that hurts, and what you would do instead.

level: seniorimportance: should knowfreq 33%

basics

~20 s

Each flushSync forces a full synchronous render and DOM commit inside the pointermove handler, dozens of times a second, blocking the main thread and defeating batching. Remove it and either let React batch normally or drive the moving element imperatively through a ref.

open as a page

A React component positions a tooltip by writing to the DOM node inside a useEffect callback, and users see the tooltip flash at the wrong position for one frame. Explain the timing that causes the flash, and what changes if the identical code runs in useLayoutEffect instead.

level: seniorimportance: should knowfreq 50%

basics

~20 s

React commits the DOM, the browser paints the un-positioned tooltip, and only then does the useEffect callback move it, so one bad frame is visible. A layout effect runs inside the commit before paint, so the user only ever sees the corrected position.

open as a page

A custom hook subscribes to an external store inside useEffect and mirrors the current value into useState on every change. Under React 19 concurrent rendering, why can components using that hook still show inconsistent values in one commit?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Because an effect cannot run in the middle of a render. A component mounting during a render seeds its copy from the store as it is at that moment, while already-mounted components still hold whatever their subscription last delivered — so one commit contains two versions.

open as a page

When a component reads an external store through useSyncExternalStore, how does React detect that the store changed partway through a render, and what does it do so the committed tree stays consistent?

level: seniorimportance: should knowfreq 31%

basics

~20 s

React remembers the snapshot each component rendered with, then re-reads it before committing and compares with Object.is. If any value moved, React throws that render away and re-renders synchronously — which only works if the snapshot value is stable between calls.

open as a page

A team wrapped almost every setState in their React 19 app in startTransition to "keep the UI responsive". Under fast typing, results now lag far longer than before and the app burns more CPU. What is the mechanism, and how would you fix it?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Priority is relative, so marking everything low-priority prioritises nothing. Each urgent keystroke preempts the in-flight low-priority render, which restarts from scratch, repeating work and delaying the commit until typing pauses. Mark only the expensive downstream update.

open as a page

You wrapped an expensive list update in React 19's startTransition, but typing in the search field is still visibly janky. What can make a transition fail to restore responsiveness?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Transitions change priority, not cost. React can only yield between units of work, so one component with a very slow render still blocks a frame; and updates can escape the transition — scheduled outside its callback, or forced synchronous — leaving the whole render urgent again.

open as a page

During a React re-render, under what conditions does React skip re-rendering a child subtree even though no React.memo is involved, and why does that almost never happen for a child written inline in the parent's JSX?

level: seniorimportance: should knowfreq 36%

basics

~20 s

React skips a child when its props object is referentially identical to the previous render, no update is pending on it, and no context it reads has changed. Inline JSX builds a new props object every render, so this rarely fires.

open as a page

A React component calls a state setter directly in its body rather than in an event handler or effect. Depending on whose state it is, the app either throws "Too many re-renders. React limits the number of renders to prevent an infinite loop." or logs a warning about updating a component while rendering a different one. Explain what React is doing in each case.

level: seniorimportance: should knowfreq 44%

basics

~20 s

Updating your own state during render makes React re-run that component immediately without committing; unguarded, it loops until React aborts with "Too many re-renders". Updating a different component's state during render is never valid and React warns, because that component already rendered in this pass.

open as a page

In React, the function passed to a state setter — as in setItems(prev => [...prev, item]) — is required to be pure. What does React do with that function that makes purity a hard requirement rather than a style rule?

level: seniorimportance: should knowfreq 42%

basics

~20 s

React does not run the updater at call time; it stores it and runs it while processing the update queue during render, possibly more than once. Anything impure inside — a side effect, or mutating the previous state — fires unpredictably or corrupts the replay.

open as a page

React can pause, resume, or entirely abandon a render pass, yet it applies the finished tree to the DOM in a single synchronous commit that never yields. Why must the commit phase be uninterruptible, and what would break if React yielded partway through it?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Render work is pure and in memory, so stopping or discarding it is free. Commit mutates the real DOM, so yielding partway would let the browser paint a mixture of two states and expose a half-updated tree to refs, effects and other scripts.

open as a page

A React 19 app wraps a state update in startTransition, but the page still freezes for roughly 150 ms on every update because one component's render function runs an expensive synchronous computation. Why does marking the update as a transition fail to keep the page responsive here?

level: seniorimportance: should knowfreq 42%

basics

~20 s

React can only yield between units of work, and one component's render call is a single indivisible unit. A transition lets React interrupt the tree walk, not a function already running, so a 150 ms component body still blocks the frame.

open as a page

React tracks the work pending on a root as "lanes" — bits in a bitmask — rather than as a single current priority number. What does that representation let React do that one number could not?

level: seniorimportance: nice to knowfreq 20%

basics

~20 s

A bitmask records a whole set of pending priorities at once, so React can render a chosen subset in one pass, keep the rest marked as still pending, and tell otherwise-similar updates apart — all with cheap bitwise set operations.

open as a page

React's reconciler keeps two fiber trees in memory at once, connected by an alternate pointer on each fiber. What are the two trees, and what does maintaining both buy React?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

React keeps the current tree, which matches what is on screen, and a work-in-progress tree it builds for the pending update; each fiber's alternate points at its counterpart in the other tree. The screen changes only when React swaps which tree is current, so unfinished work can be thrown away.

open as a page

Your team wants to adopt React 19 transitions across a large app whose shared state lives in hand-written module-level stores that components read directly during render. How do you reason about the tearing risk that introduces, and what do you do about it?

level: principalimportance: nice to knowfreq 19%

basics

~20 s

Rank each shared mutable source by whether it is read during render, how often it changes, and whether a visible disagreement would matter. Route the ones that qualify through a single tearing-safe read path, accept the rest deliberately, and budget for the interruptibility those reads give up.

open as a page

showing 31–49 of 49