alion tech studio
  • services
  • faq
  • insights
  • about
  • contact
← back home
jun 11, 2026 • 9 min read • frontend

demystifying the virtual dom: how modern frameworks render ui

By the alion tech studio engineering team

The Virtual DOM is probably the most repeated and least understood idea in front-end development. It usually gets introduced as "the thing that makes React fast," which is both an oversimplification and, in a strict sense, wrong — a Virtual DOM is almost never faster than a hand-written, surgical DOM update. Its real value is something else entirely: it lets you write UI declaratively and hands the tedious, error-prone job of synchronising the screen to the framework. This article unpacks how that actually works, what it costs, and why a wave of 2026 frameworks is quietly abandoning it.

the problem it solves isn't "the dom is slow"

The common explanation — "the DOM is slow, so we avoid touching it" — is misleading. Reading and writing DOM nodes is fast. What is expensive is the work the browser does afterward: recalculating styles, running layout (reflow), and painting. And crucially, that cost is triggered by uncoordinated updates. If your code changes ten things in a loop and reads layout in between, you can force ten synchronous reflows. The browser is not the villain; uncoordinated mutation is.

So the actual problem a framework needs to solve is: given a description of what the UI should look like, apply the smallest, best-batched set of changes to make the real DOM match — without the developer hand-writing that bookkeeping. The Virtual DOM is one answer to that problem.

what the virtual dom actually is

A Virtual DOM is just a tree of plain JavaScript objects describing your UI. When you write JSX like <li className="item">Hello</li>, it compiles to a function call that returns an object roughly like this:

{
  type: "li",
  props: { className: "item" },
  children: ["Hello"]
}

That object is cheap to create and cheap to throw away. It is not on the screen; it is a description. Nothing has touched the real DOM yet. This is the key mental shift: you are no longer issuing commands to the page, you are producing a value that represents the page.

the render / diff / commit cycle

Every update flows through three phases. Understanding them explains almost every performance question you will ever have about a framework like React:

  1. Render. State changes, so the framework calls your components and builds a brand-new Virtual DOM tree describing the next UI. This is why "re-render" does not mean "touch the DOM" — it means "run your function and produce a new description."
  2. Diff (reconciliation). The framework compares the new tree against the previous one, node by node, to find what actually changed.
  3. Commit. Only the real differences are written to the DOM, batched into as few operations as possible.

The expensive browser work happens once, in commit, on the minimum set of nodes — instead of repeatedly as a side effect of your logic.

Advertisement

why diffing is fast enough: the heuristics

Comparing two arbitrary trees is, in the general case, an O(n³) problem — hopelessly slow for a UI. Frameworks make it practical by cheating with two assumptions that hold almost all the time, bringing it down to roughly O(n):

  • Different element types produce different trees. If a node was a <div> and is now a <section>, the framework does not try to reconcile their children — it tears the old subtree down and builds the new one. Cheap to decide, occasionally wasteful, almost always correct.
  • Children in a list are identified by a stable key. Keys let the diff match an item to its previous self across reorders, instead of comparing by position.

the keys mistake everyone makes

Because keys drive list reconciliation, getting them wrong causes some of the most baffling bugs in front-end work. The classic error is using the array index as a key:

{items.map((item, i) => <Row key={i} ... />)}  // fragile

If you delete the first item, every remaining item's index shifts by one. The framework now thinks every row "changed," so it reuses the wrong DOM nodes — and any internal state, like the text in an uncontrolled input or a checkbox's checked status, stays attached to the wrong row. Use a stable identifier from your data (item.id), and index-as-key becomes safe only for static lists that never reorder. This single rule prevents a whole category of "why is my input showing the wrong value" tickets.

the virtual dom is not free

Honesty about the trade-off is what separates understanding from cargo-culting. The Virtual DOM costs you two things: memory, because you keep a copy of the UI tree around to diff against, and CPU, because every update re-runs components and walks the tree even when little changed. In a large app, an unmemoised component high in the tree can re-render thousands of descendants on every keystroke. That is why React ships memo, useMemo, and useCallback — they exist precisely to stop the Virtual DOM from doing redundant work. The fact that a framework needs escape hatches to skip re-rendering is the clearest sign that the VDOM is an overhead you manage, not a free speed-up.

React's Fiber architecture addresses a related problem: a big render could block the main thread and hurt responsiveness — the kind of delay measured by INP, one of the Core Web Vitals. Fiber makes reconciliation interruptible, so urgent work like typing can preempt a large, low-priority update.

2026: the frameworks skipping the vdom

The most interesting development is that the newest frameworks increasingly do not use a Virtual DOM at all. Signals-based, fine-grained reactivity — popularised by SolidJS and now adopted by Svelte 5's runes, Vue's Vapor mode, and Angular signals — takes a different bet. Instead of re-running a component and diffing its whole output, a signal wires each piece of state directly to the exact DOM node that depends on it. When the value changes, only that node updates; there is no tree to rebuild and no diff to compute.

This trades a little authoring ceremony for a model that often does less work and uses less memory, especially under frequent updates. It does not make the Virtual DOM obsolete — React's enormous ecosystem and mental model are not going anywhere — but it reframes the VDOM as one solution among several, rather than the definition of how modern UI works.

the takeaway

The Virtual DOM was never really about speed; it was about letting you describe the UI as a function of state and trusting the framework to reconcile reality with that description. Knowing the render/diff/commit cycle tells you why re-renders happen and how to contain them; knowing the cost tells you when to reach for memoisation or a finer-grained alternative. Understand the mechanism, and the framework stops being magic and starts being a tool you can reason about.

alion tech studio

an independent software engineering studio. we write about performance, security, and building for the web, and consult on the same.

navigation

  • services
  • faq
  • insights
  • about
  • contact

legal

  • privacy policy
  • terms of service

© 2026 alion tech studio. all rights reserved.