What is Virtual DOM in React?

Jump to

I started my web development journey in 2022, all because of DOM manipulation. Before that, I was learning C programming in college, but I found it lacked any visual aspects. 

I wanted something that gave me immediate results, something I could see and interact with.

Fortunately, I discovered a well-known website called W3Schools.

One of the first projects I built was a simple bulb on/off app, and I absolutely loved the process of building it. By the end of the day, I had something tangible—something I could show to others and say, “I built this” Even though it was a basic project, it gave me a huge sense of motivation to pursue a career in web development.

That’s when I dove into web development, starting with HTML and CSS to understand the frontend. After two months, I moved on to JavaScript, and that’s when I discovered DOM manipulation. 

I was super excited and started experimenting, manually manipulating every element on the screen—just for fun and learning.

But later, I realized an important fact:

“DOM manipulation is one of the most expensive operations in web development.”

Excessive DOM manipulation can slow down performance, so it’s always best to minimize it whenever possible. Fortunately, frameworks like React introduced the concept of the Virtual DOM, which optimizes performance by reducing direct interactions with the real DOM.

In this blog, we’ll take a deep dive into the Virtual DOM, how it works, and how it compares to the real DOM and Shadow DOM. Are you excited? Let’s get started…

What is the DOM?

Before diving into the Virtual DOM, let’s first understand the Document Object Model (DOM). The DOM is a structured representation of an HTML document, where elements are organized in a tree-like format

Each HTML tag (such as <div>, <p>, or <button>) is treated as a node in this tree, and JavaScript can dynamically manipulate these nodes to update the webpage in real-time.

For example, if you want to change the text inside a <p> element, you can use JavaScript like this:

document.getElementById("message").innerText = "Hello, World!";

This directly modifies the DOM and updates the content on the screen. However, frequent DOM updates can negatively impact performance, which is why React and other modern frameworks introduced the Virtual DOM to optimize these interactions.

Drawbacks of Updating the Real DOM

While the DOM enables dynamic content updates, frequent modifications come with significant performance challenges. Every change to the DOM triggers a complex process inside the browser, which can slow down rendering and negatively affect user experience.

The are the following drawbacks of updating the real DOM:

1. Slow Rendering Due to Reflow and Repaint

Every time an element in the DOM is updated, the browser must recalculate the layout (reflow) and then redraw the affected parts (repaint). The more elements that need updating, the longer this process takes.

For example, changing the text inside a <p> tag is a minor update, but modifying the dimensions of an element that affects other elements like changing the width of a container can trigger reflows across the entire page.

Example:

document.getElementById("box").style.width = "500px";

This change forces the browser to recalculate positions of surrounding elements, leading to a costly reflow.

2. Inefficient Updates Cause Unnecessary Renders

The real DOM does not have an efficient mechanism to detect and update only the changed elements. Even a small change might cause the browser to re-render an entire section of the page.

For example, in a list of 100 items, updating just one item may result in the entire list being re-rendered instead of just modifying the changed item. This inefficiency is a major drawback in complex web applications.

3. High Memory Usage and Performance Overhead

Each modification to the DOM requires additional memory because the browser stores multiple DOM states in memory to handle operations like undo actions and event listeners

Over time, these stored states increase memory consumption, leading to slower performance and potential memory leaks.

For instance, when adding multiple event listeners inside loops, older references to the DOM elements may remain in memory, even when they are no longer needed.

Example of an inefficient approach:

for (let i = 0; i < 1000; i++) {

 document.getElementById("btn").addEventListener("click", () => {

   console.log("Button clicked");

 });

}

This unnecessarily attaches multiple event listeners, leading to excessive memory usage.

Due to these inefficiencies, developers needed a solution to minimize direct DOM updates and improve performance. This led to the introduction of the Virtual DOM in frameworks like React, which optimizes rendering by reducing the number of direct manipulations to the real DOM.

What is Virtual DOM in react?

The Virtual DOM (VDOM) is a lightweight, in-memory representation of the real DOM. Instead of directly modifying the real DOM, React updates this virtual copy first. 

Once the updates are complete, React efficiently determines the minimal changes needed and applies them to the actual DOM in a process called Reconciliation.

This approach dramatically improves performance by reducing unnecessary updates and optimizing rendering.

How the Virtual DOM Works in React

Let’s see how React’s Virtual DOM handles UI updates efficiently:

1. Initial Render – Creating the Virtual DOM

When a React application loads for the first time, it creates a Virtual DOM tree that mirrors the real DOM structure. This virtual representation is stored in memory and is used for future updates.

For example:

function App() {

 return <h1>Hello, World!</h1>;

}

During the initial render:

  • React creates a Virtual DOM representation of <h1>Hello, World!</h1>.
  • This Virtual DOM is then converted into the real DOM, and the browser displays it.

2. State or Props Change

When the component’s state or props change, React does not modify the real DOM immediately. Instead, it updates the Virtual DOM first.

Let’s say we modify our component to include a button that updates the text:

function App() {

 const [text, setText] = React.useState("Hello, World!");

 return (

 <div>

   <h1>{text}</h1>

   <button onClick={() => setText("Hello React")}>Update Text</button>

 </div>

 );

}

When the user clicks the button:

  1. The setText function updates the state.
  2. React creates a new Virtual DOM tree with the updated text “Hello, React!”.
  3. React now has two Virtual DOM versions:
    • The previous Virtual DOM (Hello, World!).
    • The new Virtual DOM (Hello React).

3. Diffing Algorithm – Finding the Differences

React compares the previous Virtual DOM with the new Virtual DOM using an algorithm called “Diffing” to find only the changed elements.

In our case, the only change is the <h1> text.

Before update:

<h1>Hello, World!</h1>

After update:

<h1>Hello React</h1>

Instead of re-rendering the entire UI, React identifies that only the <h1> tag needs updating and ignores unchanged elements like the <button>.

4. Reconciliation 

After detecting the changes, React updates the real DOM in the most efficient way possible:

  • It applies only the necessary updates instead of replacing the entire DOM tree.
  • This reduces expensive reflows and repaints, making rendering much faster.

In our example, React only modifies the text inside the <h1> tag, leaving the <button> unchanged.

React Virtual DOM vs. real DOM

The Document Object Model (DOM) is a structured representation of an HTML document, where elements are organized in a tree-like structure. JavaScript can dynamically manipulate these elements to update content, styles, or behaviors.

For example, when you modify an element’s text using JavaScript:

document.getElementById("title").innerText = "Hello, React!";

The browser updates the DOM tree, recalculates styles, re-renders affected elements, and reflows the layout. This process can be slow and inefficient, especially for complex web applications. This is where React’s Virtual DOM comes into the picture.

The Virtual DOM (VDOM) is a lightweight, in-memory copy of the real DOM. Instead of updating the real DOM immediately, React first updates the Virtual DOM and then determines the minimal changes needed before modifying the actual DOM.

This makes UI updates much faster and more efficient because React minimizes direct DOM interactions. 

These are the following differences: 

Real DOMVirtual DOM
Represents the actual HTML structure.A lightweight, in-memory copy of the DOM.
Slow, as every update triggers reflow & repaint.Faster, as it minimizes updates.
Updates the entire DOM tree.Only updates changed elements.
Can cause lag in complex applications.Optimized rendering for smooth UI.

React Virtual DOM Pitfalls & Best Practices

The Virtual DOM makes React efficient, but it’s not a magic solution. If not used properly, it can cause performance issues, unnecessary re-renders, and increased memory usage. Here are some common problems and how to avoid them.

1. Unnecessary Re-renders

The Virtual DOM detects changes and updates only the modified parts of the UI. However, React might re-render components even when their props or state haven’t changed, slowing down performance.

Solution: Use React.memo() to prevent unnecessary re-renders and useCallback() or useMemo() to optimize function and value references.

import React, { useState, useCallback } from "react";

const ChildComponent = React.memo(({ onClick }) => {

 console.log("Child Rendered");

 return <button onClick={onClick}>Click Me</button>;

});

const ParentComponent = () => {

 const [count, setCount] = useState(0);

 const handleClick = useCallback(() => {

   console.log("Button Clicked");

 }, []);

 return (

   <div>

     <p>Count: {count}</p>

     <ChildComponent onClick={handleClick} />

     <button onClick={() => setCount(count + 1)}>Increment</button>

   </div>

 );

};

Here, React.memo() ensures that ChildComponent only re-renders when its props change, and useCallback() prevents the onClick function from being re-created on every render.

2. Large Component Trees

React compares the old and new Virtual DOM to determine updates. If the component tree is too large, this process becomes slow.

✅ Solution: Break large components into smaller, reusable ones and use lazy loading for parts of the UI that aren’t needed immediately.

const HeavyComponent = React.lazy(() => import("./HeavyComponent"));

const App = () => {

 return (

   <div>

     <h1>My App</h1>

     <React.Suspense fallback={<p>Loading...</p>}>

       <HeavyComponent />

     </React.Suspense>

   </div>

 );

};

Here, React.lazy() ensures that HeavyComponent loads only when needed, reducing the initial Virtual DOM workload.

3. Inefficient Key Usage in Lists

React uses keys to track list items efficiently. Using an index as a key can cause React to re-render more than necessary, especially when adding, removing, or reordering items.

Solution: Use unique and stable keys (like database IDs) instead of indexes.

items.map((item) => <div key={item.id}>{item.name}</div>)

With proper keys, React updates only the changed elements instead of re-rendering the entire list.

4. Excessive State Updates

Every state update triggers a re-render. Frequent updates can slow down the UI, especially when calling setState multiple times in a single function.

✅ Solution: Use the function form of setState() to batch updates efficiently.

const handleClick = () => {

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

 setCount((prev) => prev + 1); // React batched updates here

};

This ensures React updates only once instead of multiple times, improving performance.

By following these best practices, we can make the most of React’s Virtual DOM while avoiding common pitfalls.

What is Shadow DOM

There’s another term that sounds similar to the Virtual DOM—it’s called the Shadow DOM. While both deal with the DOM, they serve completely different purposes.

  • The Virtual DOM is an optimization technique that helps React update the UI efficiently.
  • The Shadow DOM is a native browser feature that helps encapsulate styles and scripts within web components.

The Shadow DOM allows developers to create isolated components in a webpage. This means that the HTML, CSS, and JavaScript inside a Shadow DOM are completely separate from the rest of the webpage.

Think of a webpage like a big whiteboard. Normally, anything you write on the board is visible to everyone and can be changed by anyone. This is how the Real DOM works—every element on the page is connected and can be affected by global styles.

But what if you wanted to write something on the board that only certain people can see and modify? 

That’s where Shadow DOM comes in! It creates a protected, hidden area on the webpage where styles and elements stay separate from the rest of the page.

Why Do We Need Shadow DOM?

Let’s say we’re adding a chatbot widget to your website. Without Shadow DOM:

  • The CSS on your website might accidentally change the chatbot’s appearance.
  • The chatbot’s styles might interfere with your existing webpage.

With Shadow DOM, the chatbot’s HTML, CSS, and JavaScript are completely isolated from the rest of your page.

  • Your website’s styles won’t affect the chatbot.
  • The chatbot’s styles won’t interfere with your site’s design.

It’s like putting the chatbot inside a box where it can work independently without affecting the outside world.

Here is the example of shadow DOM;

<div id="myComponent"></div>

<script>

 const host = document.getElementById("myComponent");

 const shadow = host.attachShadow({ mode: "open" });

 shadow.innerHTML = `

   <style>

     p { color: blue; }

   </style>

   <p>This text is inside Shadow DOM.</p>

 `;

</script>

When a developer creates a Shadow DOM, they attach a shadow root to an element. Even if your global CSS says p { color: red; }, the text inside the Shadow DOM will stay blue because its styles are protected.

Real DOM vs. Virtual DOM vs. Shadow DOM

Although Shadow DOM, Virtual DOM, and Real DOM all relate to how web pages handle elements, they serve different purposes. Shadow DOM isolates styles and scripts, Virtual DOM optimizes UI updates, and Real DOM is the actual web page structure managed by the browser. 

Here’s a quick comparison:

FeatureShadow DOMVirtual DOMReal DOM
PurposeEncapsulates styles and scripts.Improves UI performance.Represents the actual webpage.
IsolationStyles and scripts are fully isolated.No isolation, affects the entire UI.No isolation, global impact.
PerformancePrevents style conflicts but doesn’t speed up rendering.Speeds up UI updates efficiently.Slow if modified frequently.
Where It RunsBuilt into the browser for web components.Managed in memory by React.Directly handled by the browser.
Use CaseWeb components like <video> and widgets.React and similar frameworks.Default for all web pages.

Conclusion

The Virtual DOM revolutionized how UI updates work, making React faster and more efficient. While the Real DOM directly affects the page and the Shadow DOM isolates styles, the Virtual DOM optimizes rendering by reducing unnecessary updates. 

Understanding these differences helps you write better, more performant React applications. By following best practices—minimizing re-renders, using proper keys, and optimizing state updates—you can fully leverage the power of the Virtual DOM for a seamless user experience.

Leave a Comment

Your email address will not be published. Required fields are marked *

You may also like

Gujarat’s Ambitious Global Capability Centre Policy

Gujarat has unveiled a groundbreaking policy aimed at establishing 250 Global Capability Centres (GCCs) within the state, with the goal of attracting investments exceeding ₹10,000 crore over the next five

TCS SAP Cloudify framework principles

Revolutionizing SAP Deployments: TCS SAP Cloudify on Google Cloud

In today’s rapidly evolving digital landscape, enterprises are increasingly turning to cloud transformations to achieve scalable and secure infrastructure, improved resource availability, enhanced return on investment, and superior user experiences.

Categories
Scroll to Top