Skip to main content

Command Palette

Search for a command to run...

Chapter 3 - Virtual Dom

Updated
•7 min read•View as Markdown
Chapter 3 - Virtual Dom

In our series of why React Exists we covered multiple things and lastly we ended at Commit and Render Phase

In this chapter we will understand where exactly Virtual DOM lies in this phases and how it actually work , why was there a need to bring the complexity of Virtual DOM in React JS

Before I go deep in what Virtual DOM is....

I want to destory the most common definitions you will find on Youtube

Almost every tutorial says

Virtual DOM is a copy of the Real DOM

Now this above line is incomplete and in many cases , misleading

If I asked a React core team member that question , they would probably say something like:

The Virtual DOM is React's in-memory representation of the UI

Now what representation of UI actually mean

Suppose I ask you : Describe a pience of UI to me without using HTML or the browser

You might say

There is

A div

Inside it

An h1

The text is "Hello"

Then a button

The button text is "Save"

The button has an onClick handler.

Notice , You just described the UI .

You didn't create DOM nodes.

You didn't use HTML.

You simply described what should exist.

That's what React means by UI representation.

So Representation = Description

Example , Suppose we write

function App() {
    return (
        <div className="container">
            <h1>Hello</h1>

            <button onClick={save}>
                Save
            </button>
        </div>
    );
}

What does React "see" ?

Not HTML , Not DOM

It see something conceptually like

{
  type: "div",

  props: {

      className: "container",

      children: [

          {
              type: "h1",

              props: {
                  children: "Hello"
              }
          },

          {
              type: "button",

              props: {

                  onClick: save,

                  children: "Save"
              }
          }

      ]
  }
}

This entire object is a representation of your UI

Now over here React Elements Alone Are Not Enough

A React Element only answers :

What should exists ?

For example

{
   type: "button",

   props: {

      children:"Save",

      onClick: save
   }
}

It tells React : There should be a button

That's all.

But React also need to kn ow...

Has this button changed?

Should I reuse it?

Should I delete it?

Where is its parent?

What hooks belong here?

Does it have pending updates?

What priority is this update?

Should rendering pause?

What DOM node belongs to it?

Did useEffect need to run?

None of this exists inside a React Element , That's Why Fiber Exists

Fiber extends the description provided by the React Element

React Element says

Button

Text = Save

onClick = save

Fiber says

Button

Text = Save

onClick = save

↓

Parent = div

Sibling = h1

DOM Node = 0x824234

Priority = High

Needs Update = Yes

Hooks = [...]

State = ...

Effects = ...

Alternate Fiber = ...

Now React can actually manage the application.

So the flow is


Your Code
    ↓
React Elements
(describe UI)
    ↓
Fiber Tree
(manage UI)
    ↓
Commit
    ↓ 
Real DOM

One sentence you'll probably remember for years:

React Elements answer "What should the UI look like?"

Fiber answers "How do I efficiently turn that description into a real UI while supporting updates, scheduling, state, hooks, effects, and interruptions?"

Okay , Now Let's Go Back to Our Pipeline

By now , we know this much

JSX
   ↓
React Elements
   ↓
Reconciler
   ↓
Creates
   ↓
Fiber Tree
   ↓
Render Phase
   ↓
Commit Phase
   ↓
Real DOM

Now lets comeback to the question

Where exactly is the Virtual DOM ?

Suppose we write

function App() {
    return (
        <div>
            <h1>Hello</h1>
            <button>Click</button>
        </div>
    );
}

What exists after App() excecutes , until you must be able to answer

It is React Elements , which looks something like this

{
  type: "div",
  props: {
    children: [
      {
        type: "h1",
        props: {
          children: "Hello"
        }
      },
      {
        type: "button",
        props: {
          children: "Click"
        }
      }
    ]
  }
}

This is a tree of React Elements

Is this the Virtual DOM ?

Many Books says : Yes

Modern React says : Kind of... but not exactly

Why ?

Because React doesn't actually work with this object tree for very long.

Almost immediately, the Reconciler creates Fiber nodes.

Those Fibers become React's working representation of your UI.

That's why, in modern React, when people say Virtual DOM, they're usually referring to the Fiber tree, even though historically the term came from the React Element tree.

So the phrase "Virtual DOM" is more of a concept than a single data structure.

Let's See an Example how Virtual DOM is actually helpful

function App() {
    return (
        <div>
            <h1>Hello</h1>
            <button>Save</button>
        </div>
    );
}

React build a representation like :

div
├── h1
│     └── Hello
└── button
      └── Save

Now state changes

function App() {
    return (
        <div>
            <h1>Hello Avez</h1>
            <button>Save</button>
        </div>
    );
}

React renders again

New representation :

div
├── h1
│     └── Hello Avez
└── button
      └── Save

Now the Reconciler compares :

Old                  New

div                  div
 ↓                    ↓
h1                   h1
 ↓                    ↓
Hello      →      Hello Avez
 ↓                    ↓
button             button
 ↓                    ↓
Save                 Save

The only difference is the text node under <h1>.

So the Reconciler marks that Fiber with an Update flag.

During the Commit Phase, ReactDOM performs just:

textNode.nodeValue = "Hello Avez";

The <button> isn't recreated.

The <div> isn't recreated.

The <h1> isn't recreated.

Only the text changes.

Here's Something Important

Many people imagine the diff like this:

Old DOM
↓

Compare

↓

New DOM

No.

React compares its own in-memory UI representation.

The browser DOM is touched only after the comparison is complete.

That's why React can even abort a render halfway through in concurrent rendering—because it hasn't modified the real DOM yet.

So is the Virtual DOM a Copy of the Real DOM

Let's compare

Real DOM Virtual DOM
Owned by browser Owned by React
Contains actual DOM nodes Contains React's UI representation
Expensive to mutate Cheap JavaScript objects
Directly affects what users see Doesn't affect the screen until commit
Platform-specific Platform-agnostic

People often ask :

Does React compare the old DOM with the new DOM?

No.

It compares the current Fiber tree (representing the current UI) with the work-in-progress Fiber tree (representing the newly rendered UI).

The outcome of that comparison is a set of effect flags that tell the renderer exactly what to do during the commit phase.

This is one of the reasons Fiber became such a significant architectural change—it unified the concepts of the Virtual DOM, scheduling, and reconciliation into a single working data structure.

Now until now this is the Mental Model So Far , we've built over the last two chapters

                JSX
                 ↓

          React Elements  
                 ↓

        React Reconciler
          Creates / Updates
                 ↓

      Work-In-Progress Fiber Tree
                 ↓

      Compare with Current Fiber Tree
                 ↓

      Reconciliation (Diff)
                 ↓

        Effect Flags Generated
                 ↓

         ReactDOM Commit Phase
                 ↓

             Real DOM
                 ↓

           Browser Paint

Now Before moving to the Next Chapter

I want to leave you with one question to think about

Imagine this JSX :

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

Now it becomes

<ul>
  <li>B</li>
  <li>A</li>
  <li>C</li>
</ul>

How does React know that A and B were swapped, instead of thinking:

  • Delete A

  • Create new A

  • Delete B

  • Create new B

This single question gave birth to one of React's most famouse concepts :

Keys and the Reconcilation Algorithm