Skip to the solution
EasyFrontend6 min read

What is the Virtual DOM in React?

404 views

The problem

Question presented to candidate: "What is the Virtual DOM, and why does React use one?"

What a strong answer should cover:

  • A lightweight in-memory representation of the UI, made of plain objects (React elements). It is not a browser feature and not a copy of the DOM.
  • On each render React builds a new tree, diffs it against the previous one (reconciliation), and applies only the differences to the real DOM.
  • Why: real DOM operations are expensive relative to object comparison, and touching it triggers layout and paint.
  • The honest framing: it is not faster than optimal hand-written DOM code. Diffing is extra work vanilla code skips. What it buys is making the declarative model fast enough to be practical.
  • The diffing heuristics that make it O(n): different element types mean discard and rebuild; keys identify children across renders.
  • Consequence of the type heuristic: changing an element's type unmounts the subtree and destroys its state.
  • Fiber is the implementation that made this interruptible; the Virtual DOM is the data model, Fiber is the scheduler.
  • Related but distinct: the shadow DOM is a browser encapsulation feature with no connection to this.

Clarifying questions expected:

  • "Do you want the concept, or the diffing heuristics?"

Code / implementation expected: Optional. Showing that an element is a plain object makes the point faster than prose.

  • virtual dom
  • performance
  • reconciliation
  • dom

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

6 min read · 9 sections

Try it in the playground

Open any example in the playground to run and change it.

ReactElements are plain objects, and a type change destroys the subtree
import { useState } from "react";

function Counter() {
  const [n, setN] = useState(0);
  return (
    <button onClick={() => setN((v) => v + 1)}>
      clicked {n} times
    </button>
  );
}

// Two wrappers that render almost identical output — but they are DIFFERENT
// element types, which is all reconciliation cares about.
function DivWrapper({ children }) {
  return <div style={{ padding: 10, border: "2px solid #4f46e5", borderRadius: 8 }}>{children}</div>;
}
function SectionWrapper({ children }) {
  return <section style={{ padding: 10, border: "2px solid #16a34a", borderRadius: 8 }}>{children}</section>;
}

export default function App() {
  const [asSection, setAsSection] = useState(false);
  const Wrapper = asSection ? SectionWrapper : DivWrapper;

  // The element is just data — inspect it.
  const element = <Counter />;
  const shape = {
    typeofElement: typeof element,
    typeIsTheFunction: element.type === Counter,
    keys: Object.keys(element).join(", "),
    frozen: Object.isFrozen(element),
  };

  return (
    <div style={{ padding: 24, fontFamily: "system-ui", lineHeight: 1.6, maxWidth: 480 }}>
      <h4 style={{ marginTop: 0 }}>An element is a plain object</h4>
      <pre style={{ background: "#f6f6f6", padding: 10, borderRadius: 6, fontSize: 12 }}>
        {JSON.stringify(shape, null, 2)}
      </pre>

      <h4>Changing the wrapper TYPE destroys the child state</h4>
      <Wrapper>
        <Counter />
      </Wrapper>

      <p style={{ marginTop: 10 }}>
        <button onClick={() => setAsSection((s) => !s)}>
          swap wrapper to a &lt;{asSection ? "div" : "section"}&gt;
        </button>
      </p>

      <p style={{ color: "#666", fontSize: 13 }}>
        Click the counter a few times, then swap the wrapper. The count resets to
        zero — React saw a different element type, so it discarded the whole
        subtree and mounted a fresh one rather than trying to match it up.
      </p>
    </div>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 17 of 119 in React.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All React.js questions
Up nextEasy

What is React and its main features?

Continue