Virtual DOM in React

Understanding React's Virtual DOM and its benefits

By Hank Kim

Virtual DOM in React

Understanding React's Virtual DOM and its benefits

1. What is the Virtual DOM?

  • DOM (Document Object Model) Represents the UI as a tree structure. Updating the DOM directly is expensive because each change can trigger layout and paint operations in the browser.

  • Virtual DOM (VDOM) A lightweight, in-memory object representation of the actual DOM. It is essentially a “virtual copy” of the DOM that React maintains to determine the minimal set of updates needed.

  • Key Idea Instead of updating the real DOM on every change, React:

    1. Updates the Virtual DOM first.
    2. Runs a diffing algorithm to detect changes between the old and new Virtual DOM.
    3. Applies only the necessary updates to the real DOM.

2. Why Virtual DOM?

  • Direct DOM manipulation is costly; frequent updates cause reflows and repaints, leading to poor performance.
  • Virtual DOM enables efficient batch updates:

    • Compute what has changed instead of re-rendering the entire UI.
    • Apply updates selectively to reduce overhead.
  • It is not “always faster than direct DOM manipulation,” but it provides a predictable and scalable way to manage updates in complex apps.

3. How Does It Work? (Update Cycle)

Step 1: Trigger

  • A change in state or props triggers re-rendering of the component.
  • React executes the component function again to produce a new Virtual DOM tree.

Step 2: Diffing

  • React compares the new Virtual DOM with the previous Virtual DOM.
  • This diffing algorithm detects additions, deletions, and updates.
  • Keys are critical here:

    • Keys act as unique identifiers for list elements.
    • With correct keys, React reuses existing DOM nodes.
    • With unstable keys (e.g., array indices), React may reuse nodes incorrectly, causing UI bugs.

Step 3: Reconciliation

  • React builds a change plan (patch list) based on diffing results.
  • It decides which nodes to update, remove, or reuse.
  • This stage does not yet touch the actual DOM.

Step 4: Commit

  • React applies all changes to the real DOM in a single batch.
  • This ensures atomic updates: no partial intermediate states.
  • After the commit:

    • useLayoutEffect runs immediately (after DOM mutation, before paint).
    • useEffect runs afterward (post-paint).

4. React Fiber

  • Problem: As apps grow, reconciliation becomes expensive (large trees take time to diff).
  • Solution: React Fiber (since React 16):

    • Breaks reconciliation into units of work.
    • Uses prioritization: urgent updates (like user input) are handled before non-urgent ones.
    • Leverages requestIdleCallback-like scheduling to pause/resume rendering.
  • Enables React to be responsive even during heavy updates.

5. Batching Updates

  • Multiple state updates in a short period are batched together before reconciliation.
  • Example:

    setCount((c) => c + 1);
    setCount((c) => c + 1);
    

    → React batches these so the component only re-renders once.

  • This is why setState behaves asynchronously.

6. Common Misunderstandings

  • Virtual DOM is not inherently faster than manual DOM updates.

    • It introduces overhead (extra memory and diffing computation).
    • The benefit comes from structured batching and selective updates, not raw speed.
  • Reconciliation ≠ Commit

    • Reconciliation: calculate differences.
    • Commit: apply changes to the real DOM.

7. Key Question: Why Are Keys Important?

Q: Why is the key prop important in lists during reconciliation? A:

  • Keys help React correctly identify which elements have changed.
  • With stable, unique keys:

    • React can update only the changed items.
    • Performance is improved, and UI correctness is preserved.
  • With unstable keys (like array indices):

    • React may mistakenly reuse nodes when order changes.
    • This can cause incorrect state reuse and UI bugs.

8. Summary

  • Virtual DOM = in-memory tree representation of the real DOM.
  • Process:

    1. State/props change → New Virtual DOM created.
    2. Diffing → Compare new vs old Virtual DOM.
    3. Reconciliation → Build update plan.
    4. Commit → Apply minimal changes to the real DOM.
  • Fiber improves scheduling and prioritization.
  • Batching ensures efficient state updates.
  • Keys are critical for reconciliation in lists.