React Virtual DOM Explained
A beginner-friendly guide to how React uses the Virtual DOM to render, compare, and update the UI efficiently.

React is popular because it lets developers build user interfaces declaratively. Instead of imperatively changing DOM nodes whenever state changes, we describe what the UI should look like for a given state, and React efficiently updates the page to match.
Under the hood, React minimizes costly browser work— style recalculation, layout, paint and reflow by computing the smallest set of DOM changes and applying them.
The Problem: Direct DOM manipulation is expensive
The browser’s DOM represents the actual HTML elements on the page. When we change the DOM directly, the browser needs to recalculate styles, update layout, repaint pixels, and sometimes reflow large parts of the page.
document.querySelector("#title").textContent = "Updated Title";
document.querySelector("#count").textContent = count;
A few updates are fine. But in a large application with many frequent UI changes, manually tracking and updating the right DOM nodes becomes difficult and error-prone.
The main problems are:
Direct DOM manipulation can be slow if done too often.
Manually keeping UI in sync with data is complex.
Updating more DOM nodes than necessary hurts performance.
Code becomes harder to maintain as the UI grows.
React solves this by introducing a layer between your application state and the real browser DOM.
That layer is the Virtual DOM.
What Is the Virtual DOM?
The Virtual DOM is a lightweight JavaScript representation of the real DOM.
It is not the actual browser DOM. It is simply an object-based description of what the UI should look like.
For example, this JSX:<h1>Hello React</h1>
can be represented conceptually like this:
{ type: "h1", props: { children: "Hello React" } }
This object does not appear on the screen. It only describes the UI.
React uses this description to decide how the real DOM should be created or updated.
Real DOM vs Virtual DOM
The Real DOM is the actual browser representation of the page.
The Virtual DOM is a lightweight JavaScript representation of what the UI should look like.
| Real DOM | Virtual DOM |
|---|---|
| Managed by the browser | Managed by React |
| Represents actual UI elements | Represents UI as JavaScript objects |
| Updating it can trigger layout and repaint | Updating it is mostly JavaScript work |
| Direct changes can be expensive | Cheap to create and compare |
What the Virtual DOM Solves
The Virtual DOM helps React answer one important question:
What is the smallest set of changes needed to update the real page?
Instead of immediately changing the browser DOM whenever state changes, React first creates a new Virtual DOM tree. Then it compares the new tree with the previous one. This comparison process is called diffing or reconciliation.
After React finds what changed, it updates only the required parts of the Real DOM.
Initial Render Process in React
Let’s say we have this component:
function App() {
return <h1>Hello React</h1>;
}
During the first render, React follows this process:
Component → JSX → Virtual DOM tree → Real DOM nodes → Browser screen
Step by step:
React calls the component.
The component returns JSX.
React creates a Virtual DOM tree from that JSX.
React creates matching real DOM nodes.
The browser displays the UI.
At this point, React also keeps the Virtual DOM tree in memory. This saved tree is important because React will compare it with the next tree when something changes.
What Happens When State or Props Change?
React components re-render when their state or props change.
Example:
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<h1>Counter</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
}
Initially, the UI shows Count : 0. When the button is clicked, setCount(count + 1) updates the state. React then runs the component again and creates a new Virtual DOM tree. The new UI should show count: 1
But React does not immediately replace the whole page. Instead, it compares the old Virtual DOM tree with the new Virtual DOM tree.
New Virtual DOM Tree Is Created
Before the state update, React had an old Virtual DOM tree.
Conceptually:
{
type: "p",
props: {
children: "Count: 0"
}
}
After the state update, React creates a new Virtual DOM tree:
{
type: "p",
props: {
children: "Count: 1"
}
}
Now React has two trees:
Old Virtual DOM tree: Count: 0
New Virtual DOM tree: Count: 1
React compares them to find what changed.
What Is Diffing?
Diffing means comparing the old Virtual DOM tree with the new Virtual DOM tree.
React checks both trees and asks:
What changed between the previous UI and the new UI?
For the counter example, React sees that only the text changed:
Count: 0 → Count: 1
The surrounding <div>, <h1>, and <button> did not change. So React does not recreate everything. It updates only the changed text in the real DOM.
What Is Reconciliation?
Reconciliation is the process React uses to decide how to update the UI after comparing the old and new Virtual DOM trees.
In simple words:
Reconciliation = comparing old UI with new UI and deciding what real DOM changes are needed
The result of reconciliation is a minimal set of changes that need to be applied to the real DOM.
How React Finds Minimal Changes
React follows practical rules while comparing elements: If the element type is the same, React keeps the existing DOM node and updates only what changed.
<p>Count: 0</p>
<p>Count: 1</p>
The element type is still p, so React updates the text. But if the element type changes:
<p>Hello</p>
<h1>Hello</h1>
React treats it as a different structure and may replace the old node with a new one. For lists, React uses key values to identify items.
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
Keys help React understand which item was added, removed, or changed. Good keys make updates more predictable and efficient.
Updating the Real DOM
After diffing and reconciliation, React updates the real DOM.
For example, before update:
<div>
<h1>Counter</h1>
<p>Count: 0</p>
<button>Increase</button>
</div>
After Update:
<div>
<h1>Counter</h1>
<p>Count: 1</p>
<button>Increase</button>
</div>
Only part that changed: <p>Count: 1</p>
So React updates only that part in the real DOM.
This final step, where React applies changes to the real DOM, is often called the commit phase.
React Render, Diff, and Commit Flow
At a high level, React updates follow this flow:
State or props change
↓
Component re-renders
↓
New Virtual DOM tree is created
↓
Old tree and new tree are compared
↓
React finds the required changes
↓
React updates the real DOM
↓
Browser displays the updated UI
In simple: Render → Diff → Commit
Render: React calls components and creates a new Virtual DOM tree.
Diff: React compares the old and new Virtual DOM trees.
Commit: React applies the required changes to the real DOM.
Why the Virtual DOM Improves Performance
The Virtual DOM improves performance by reducing unnecessary real DOM updates.
The real DOM can be expensive to update frequently because browser updates may involve layout calculation, repainting, and reflow.
The Virtual DOM allows React to do most of the comparison work in JavaScript first. Then React updates only the parts of the real DOM that actually changed.
However, the Virtual DOM is not magic. It does not mean React is always faster than direct DOM manipulation in every situation.
The bigger benefit is that React gives developers a simple mental model:
Describe the UI based on state, and React will update the DOM efficiently.
This makes applications easier to build, reason about, and maintain.
Complete Mental Model
Think of the Virtual DOM as a draft copy of the UI.
When something changes:
React creates a new draft.
React compares the new draft with the old draft.
React finds the differences.
React updates only the necessary parts of the real page.
Old UI draft
+
New UI draft
↓
Find differences
↓
Update real DOM
Final Summary
The Virtual DOM is a lightweight JavaScript representation of the UI.
React uses it to avoid unnecessary real DOM updates. When state or props change, React creates a new Virtual DOM tree, compares it with the old tree, finds the minimum required changes, and updates only the changed parts of the real DOM.
The full flow is:
Initial render: Component → Virtual DOM → Real DOM
Update: State/props change → New Virtual DOM → Diffing → Minimal DOM updates → Real DOM updated
