How Does React Reconciliation Work?
Learn how React reconciliation diffs element trees using type and key heuristics to compute minimal, fast DOM updates.
Expected Interview Answer
Reconciliation is React’s algorithm for comparing a newly rendered element tree against the previous one and computing the minimal set of DOM mutations needed to update the real DOM, using heuristics like element type and `key` to make the diff run in linear time instead of the exponential cost of a naive general tree-diff.
A fully general tree-diffing algorithm is O(n^3), which is impractical for UI updates, so React applies two simplifying assumptions: elements of different types produce fundamentally different trees, so React tears down the old subtree and builds a new one rather than trying to diff across types; and elements of the same type are compared by their props, keeping the same underlying DOM node and instance while only patching what changed. For lists, React uses the `key` prop to match elements between renders by identity rather than by array position; without stable keys, React falls back to comparing by index, which can cause it to preserve the wrong internal state or DOM node when items are inserted, removed, or reordered in the middle of a list. Since React 18’s concurrent-capable Fiber architecture, reconciliation work is broken into interruptible units so the browser can stay responsive, and it can compute the diff without necessarily committing it immediately, but the underlying same-type/same-key matching heuristics for that diff are unchanged.
- Reduces tree-diff cost from an impractical general case to a fast linear-time heuristic
- Reuses existing DOM nodes and component instances instead of always recreating them
- Stable keys let React correctly match reordered list items to their existing state
- Fiber’s interruptible units keep reconciliation from blocking user interaction
AI Mentor Explanation
React reconciliation is like a scorer comparing the new lineup card to the previous one by matching each player’s jersey number, not by which row they happen to sit in. If a player with the same number is still there, the scorer just updates that player’s runs instead of writing a whole new card entry. If jersey numbers are missing and only row position is used, swapping two batters in the order can make the scorer wrongly credit the wrong player’s stats to the wrong name. That match-by-identity-not-position approach is exactly how the key prop lets React reconciliation track list items correctly.
Step-by-Step Explanation
Step 1
Render produces a new element tree
State or props change triggers a fresh render, producing a new tree of React elements.
Step 2
Compare element type at each node
If the type differs from the previous render, React discards the old subtree and builds a new one.
Step 3
Match same-type elements by key
For lists, React uses the key prop to identify which existing item corresponds to which new item.
Step 4
Patch only what changed
Matched elements keep their DOM node/instance; only changed props or children are patched.
What Interviewer Expects
- Understanding of the type-then-key matching heuristic
- Clear explanation of why array index is a poor key for dynamic lists
- Awareness of the O(n^3) general tree-diff problem this heuristic avoids
- Mention of Fiber’s interruptible units as the underlying scheduling mechanism
Common Mistakes
- Using array index as key for lists that can be reordered, inserted into, or filtered
- Confusing reconciliation with the virtual DOM diffing concept without explaining the key/type heuristics
- Assuming reconciliation always recreates DOM nodes on every render
- Not knowing that a changed element type causes full subtree teardown rather than a patch
Best Answer (HR Friendly)
“React reconciliation is how React figures out what actually changed between the old version of the UI and the new one, so it only updates the parts of the real page that need it. It uses tricks like comparing element types and, for lists, unique keys, so items that stayed the same aren’t needlessly recreated — which is why giving list items a stable, unique key matters so much.”
Code Example
// Bad: index as key breaks when items are reordered/removed
todos.map((todo, index) => <TodoItem key={index} todo={todo} />)
// Good: stable identity lets React match items correctly across renders
todos.map((todo) => <TodoItem key={todo.id} todo={todo} />)Follow-up Questions
- Why is using array index as a key problematic for reorderable lists specifically?
- How does the Fiber architecture change how reconciliation work is scheduled?
- What happens to component state when an element’s type changes between renders?
- How does React.memo interact with the reconciliation process?
MCQ Practice
1. What does React do when an element’s type changes between renders?
Different element types are assumed to produce fundamentally different trees, so React rebuilds rather than diffs across types.
2. Why is using array index as a key risky for a reorderable list?
When items reorder, index-based keys can point React to the wrong existing element, causing state to attach incorrectly.
3. What complexity class does React’s reconciliation heuristic avoid compared to a general tree diff?
A fully general tree-diff algorithm is O(n^3); React’s type/key heuristics bring this down to roughly linear time.
Flash Cards
What is reconciliation? — React’s algorithm for diffing element trees to compute minimal DOM updates.
Two core heuristics? — Different types rebuild the subtree; same types match and patch by key.
Why avoid index as key? — It can cause React to misassign state/DOM nodes when list order changes.
What architecture schedules this work? — Fiber, which breaks reconciliation into interruptible units.