Contact

What is Virtual DOM?

Definition

The virtual DOM is a lightweight in-memory representation of what the user interface should look like, held as plain JavaScript objects. Libraries such as React build a new virtual tree when state changes, compare it with the previous one (reconciliation) and apply only the differences to the real DOM. It lets developers describe the end state of the UI instead of manipulating the DOM step by step, but it is not always faster than targeted hand-written DOM updates.

Also known as: VDOM, vDOM, virtual DOM diffing

Flow showing a state change producing a new virtual DOM, diffed against the previous one, with only changes patched to the real DOM

Compared with updating the DOM by hand

In the imperative approach, every change is a list of instructions for the DOM: find this element, change its text, add that class, append a row to this list. As an application grows, tracking which part of the screen must change after which event becomes hard, and "the data changed but the screen didn't" bugs multiply.

With a virtual DOM you describe what the UI should look like for the current data. The library turns that description into a tree of objects in memory, compares it with the previous tree and applies the smallest set of changes to the real DOM. React's older documentation defined it as a concept "where an ideal, or 'virtual', representation of a UI is kept in memory and synced with the 'real' DOM by a library such as ReactDOM". That syncing process is called reconciliation.

Render, diff, commit

  1. Render: state or props change; the affected component functions run again and return a new element tree.
  2. Diff: the library matches the new tree against the old one and works out which attributes, text nodes or children changed.
  3. Commit: only those DOM nodes are touched. React's current docs say it plainly: React only changes DOM nodes if there is a difference between renders. That is why text typed into an input survives when its component re-renders.

Two heuristics and the key prop

Finding the minimal set of operations between two arbitrary trees is expensive; React's legacy docs note that general-purpose algorithms run in O(n³). React uses a linear heuristic instead, built on two assumptions: elements of different types produce different trees, and developers can mark which children stay stable between renders with a key.

// Different component type at the same position: subtree and its state are reset
{isLoggedIn ? <Dashboard /> : <LoginForm />}

// List items need a stable identity, not the array index
{items.map((item) => <Row key={item.id} item={item} />)}

Using the index as a key means that after a reorder the wrong rows get reused, and uncontrolled inputs can end up showing each other's values. React's guide to preserving and resetting state shows how the same component at the same position keeps its state, and how a key deliberately changes that match.

The "virtual DOM is always faster" myth

The virtual DOM is extra work on top of the DOM: every update allocates a new tree and spends CPU time comparing it. A hand-written update that knows exactly what changed skips all of that and is, in principle, faster. The real benefit lies elsewhere. Developers write declarative code, the library filters out needless DOM operations, and a large application gets reasonable performance without hand-tuning every update. Compiler-based tools such as Svelte and fine-grained reactive libraries such as Solid deliver the same declarative model without virtual DOM diffing at all.

In practice, slow React apps are rarely slow because of the virtual DOM itself. The usual culprits are large component trees re-rendering for no reason, very long unvirtualised lists and heavy JavaScript bundles.

What crawlers and servers see

The virtual DOM exists only inside JavaScript running in the browser. Search engine crawlers never see it; they evaluate the HTML and the rendered DOM it produces. When server-generated HTML is taken over by React in the browser, the process is called hydration: React matches the server-rendered DOM against its own tree and warns when the two disagree.

Related terms

← Back to the glossary