Virtual DOM
A virtual DOM keeps a lightweight programmatic tree as the source of truth, diffs it against the previous snapshot, and applies only the resulting minimal patches to the real DOM.
Definition
The virtual DOM is an in-memory tree of plain objects describing desired UI. On state change, a new tree is built, compared with the previous one via a diffing algorithm, and the computed patch is applied to the browser DOM. The purpose is to batch and minimize direct DOM mutations, which are expensive relative to object manipulation.
Context and scope
The rendering model of React-class libraries and many view layers. Contrasted with fine-grained signals-based reactivity that updates exactly the affected nodes without tree diffing.
Common misconceptions
- The virtual DOM is faster than the DOM — it is a batching and scheduling strategy; careless re-renders still slow apps down
- Diffing always finds the minimal patch — heuristics like keys bound the search, not guarantee optimality
- It eliminates manual DOM reasoning — list reconciliation rules such as stable keys remain the developer job
Anti-patterns
- Rendering entire component trees on every keystroke and letting the diff do the thinking
- Using array indexes as keys on reorderable lists, degrading state-to-item mapping and diff quality
- Treating reconciliation as a free abstraction and profiling nothing after migration
Related concepts
Related examples
Authoritative source
What it is
Direct imperative DOM updates scatter mutations across the codebase and cause redundant work. A virtual DOM centralizes the desired end state: build the new description, diff old versus new, commit real changes once. The DOM then transitions from consistent state to consistent state.
How it works
Reconciliation walks both trees, comparing element types and keys. Type changes replace subtrees; keys match children across reorderings so state follows items. Resulting operations are applied in a commit phase, often batched inside one task or microtask flush. Libraries vary on scheduling: synchronous flushes, time slicing, or concurrent transitions.
When it matters
The model shines for declarative UI with complex conditional structure, cross-platform rendering targets beyond the browser, and frameworks needing escape hatches to imperative nodes. On update-heavy numeric dashboards, fine-grained reactivity often wins by touching only affected bindings.
Pitfalls
The diff itself costs CPU proportional to tree size, so memoization and component boundaries matter more than the abstraction. Key misuse is the classic silent bug: state attaches to the wrong item after reorder. Escape hatches such as refs exist precisely because the abstraction leaks on focus, selection, and third-party widget integration.