Virtual DOM & Reconciliation
React diffs a virtual tree against the previous one to update the DOM efficiently.
When state changes, React builds a new virtual DOM tree describing the desired UI, then compares it to the previous tree. This diffing process is called reconciliation.
The payoff
React figures out the minimal set of real DOM changes and applies only those. You write UI declaratively as a function of state, and React handles the efficient updates.
Example
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
// Only the text node inside <p> is updated on each click,
// not the whole component's DOM.
return (
<div>
<h2>Counter</h2>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}When to use it
- A real-time dashboard updates dozens of metric cards on each data push; React's reconciler diffs the virtual tree and patches only the changed text nodes, keeping the page smooth.
- A large form with conditional fields relies on React's reconciliation to add or remove groups of inputs without re-rendering unrelated fields.
- An animated list relies on React's ability to detect which items are new, moved, or removed by key, enabling targeted CSS transition triggers instead of full repaints.
More examples
State update triggers reconciliation
Each click updates state; React diffs the virtual tree and patches only the text inside <strong>, not the whole div.
import { useState } from 'react';
function TemperatureDisplay() {
const [temp, setTemp] = useState(20);
return (
<div>
<p>Temperature: <strong>{temp}Β°C</strong></p>
<button onClick={() => setTemp(t => t + 1)}>Heat</button>
</div>
);
}Same component type, patch only
When only props change, React patches the existing DOM element's class and text instead of replacing the node.
function StatusMessage({ status }) {
// React updates only changed attributes/text, not the whole DOM node
return (
<p className={`status status--${status}`}>
{status === 'ok' ? 'All systems go.' : 'Check required.'}
</p>
);
}Key causes full unmount/remount
Demonstrates that changing a key tells React's reconciler the element is a new node, bypassing diffing and resetting state.
function VideoPlayer({ src }) {
// Changing key forces React to destroy and recreate the <video> element
// so the browser loads the new source from scratch.
return <video key={src} src={src} controls />;
}
Discussion