Under the Hood of React: The Magic of Virtual DOM

Isuru Dinusha
5 min readMay 17, 2024

--

React has become a dominant force in front-end development, known for its declarative style and impressive performance. But what makes React so efficient? The answer lies in its clever use of the Virtual DOM (VDOM). This article will delve into the inner workings of React, unraveling the mysteries of VDOM and how it contributes to a seamless user experience.

Understanding the DOM:

Before we dive into the VDOM, it’s essential to understand the Document Object Model (DOM). The DOM is a tree-like representation of a web page’s structure, where each HTML element is a node in the tree. When we interact with a website, JavaScript manipulates this DOM, changing element attributes, and adding or removing nodes, leading to visible changes on the page. However, directly manipulating the DOM can be slow and inefficient.

Enter the Virtual DOM:

React’s VDOM is a lightweight, in-memory representation of the actual DOM. It’s essentially a JavaScript object that mirrors the structure of the real DOM, holding information about elements, their properties, and content. When changes occur in your React application, they’re first applied to this VDOM.

The Reconciliation Process:

Here’s where the magic happens: React employs a powerful algorithm called reconciliation to compare the current VDOM with the previous version. This process efficiently identifies the specific changes that need to be made to the real DOM. Instead of blindly updating the entire DOM, React surgically targets only the modified nodes, minimizing the number of costly DOM operations.

How It Works:

  1. Trigger: An event like user input or data change triggers an update in a React component.
  2. VDOM Update: React updates the relevant parts of the VDOM to reflect the new state of the application.
  3. Diffing: React compares the updated VDOM with the previous one, identifying the differences.
  4. Patching: Based on the diffing results, React creates a minimal set of instructions to update the real DOM, only touching the nodes that require changes.

Example: Updating a Child's Details

When the button is clicked, the child’s data changes. This includes their name, age, and hobby. Clicking the button triggers a random selection from an array, which then updates and displays the new values.

Additionally, you’ll see a green color paint flash, highlighting areas of the page (in green) that need to be repainted in the DOM.


<body>
<div class="App">
<h2>Child Details:</h2>
<p id="name">Name: John</p>
<p id="age">Age: 10</p>
<p id="hobby">Hobby: Football</p>
<button onclick="updateChildDetails()">Update Details</button>
</div>

<script>
function updateChildDetails() {
const names = ["John","Alice", "Bob", "Charlie", "Diana", "Ella"];
const ages = [8, 9, 10, 11, 12];
const hobbies = ["Football","Basketball", "Drawing", "Reading books"];

const child = {
name: names[Math.floor(Math.random() * names.length)],
age: ages[Math.floor(Math.random() * ages.length)],
hobby: hobbies[Math.floor(Math.random() * hobbies.length)]
};

document.getElementById("name").innerText = "Name: " + child.name;
document.getElementById("age").innerText = "Age: " + child.age;
document.getElementById("hobby").innerText = "Hobby: " + child.hobby;
}
</script>

Now we remove values from the name and hobby arrays, leaving only one value in each array.

<script>
function updateChildDetails() {
const names = ["John"];
const ages = [8, 9, 10, 11, 12];
const hobbies = ["Football"];

const child = {
name: names[Math.floor(Math.random() * names.length)],
age: ages[Math.floor(Math.random() * ages.length)],
hobby: hobbies[Math.floor(Math.random() * hobbies.length)]
};

document.getElementById("name").innerText = "Name: " + child.name;
document.getElementById("age").innerText = "Age: " + child.age;
document.getElementById("hobby").innerText = "Hobby: " + child.hobby;
}
</script>

Now, even if the name and hobby values remain the same, every repaint of the DOM updates all three: name, age, and hobby.

This is what happens in normal JavaScript: even if the values are the same, they get repainted over and over again.

Let’s replicate the same process using React.

Initially, you’ll notice that the name, age, and hobby have multiple values, and they change randomly when the button is clicked. The green flash indicates that these elements are repainted because their values changed.

function App() {
const [childName, setChildName] = useState("John");
const [childAge, setChildAge] = useState(10);
const [childHobby, setChildHobby] = useState("Football");

const changeChildInfo = () => {
const names = ["John", "Alice", "Bob", "Charlie", "Diana", "Ella"];
const ages = [8, 9, 10, 11, 12];
const hobbies = ["Football", "Basketball", "Drawing", "Reading"];

const randomNameIndex = Math.floor(Math.random() * names.length);
const randomAgeIndex = Math.floor(Math.random() * ages.length);
const randomHobbyIndex = Math.floor(Math.random() * hobbies.length);

setChildName(names[randomNameIndex]);
setChildAge(ages[randomAgeIndex]);
setChildHobby(hobbies[randomHobbyIndex]);
};

return (
<div>
<h3>Child Details:</h3>
<div className="info">
<p>Name:{childName}</p>
<p>Age:{childAge}</p>
<p>Hobby:{childHobby}</p>
</div>
<button onClick={changeChildInfo}>Update Details</button>
</div>
);
}

Now we remove values from the name and hobby arrays, leaving only one value in each array.

function App() {
const [childName, setChildName] = useState("John");
const [childAge, setChildAge] = useState(10);
const [childHobby, setChildHobby] = useState("Football");

const changeChildInfo = () => {
const names = ["John"];
const ages = [8, 9, 10, 11, 12];
const hobbies = ["Football"];

const randomNameIndex = Math.floor(Math.random() * names.length);
const randomAgeIndex = Math.floor(Math.random() * ages.length);
const randomHobbyIndex = Math.floor(Math.random() * hobbies.length);

setChildName(names[randomNameIndex]);
setChildAge(ages[randomAgeIndex]);
setChildHobby(hobbies[randomHobbyIndex]);
};

return (
<div>
<h3>Child Details:</h3>
<div className="info">
<p>Name:{childName}</p>
<p>Age:{childAge}</p>
<p>Hobby:{childHobby}</p>
</div>
<button onClick={changeChildInfo}>Update Details</button>
</div>
);

Now, you’ll notice that for every button click, only the age gets repainted. Unlike in normal JavaScript, all three values are not repainted. This demonstrates the use of Virtual DOM (VDOM), which only repaints the necessary parts even when we write it in the code, like an AI.

Benefits of Virtual DOM:

  • Improved Performance: By minimizing DOM manipulations, React significantly reduces the number of expensive updates to the real DOM, leading to faster rendering and a smoother user experience.
  • Simplified Development: Developers can focus on component logic and state management without worrying about low-level DOM manipulations, making development faster and more efficient.
  • Cross-Platform Compatibility: The virtual DOM allows React to run seamlessly across different platforms, including web, mobile, and even server-side rendering.

Beyond the Basics:

  • Batching: React intelligently groups multiple updates together and applies them in a single batch to further enhance performance.
  • Selective Rendering: Using lifecycle methods like shouldComponentUpdate, developers can control when a component needs to re-render, preventing unnecessary updates.

Conclusion:

The VDOM is a key innovation behind React’s success. By strategically leveraging this in-memory representation and a powerful reconciliation process, React optimizes DOM manipulations, resulting in faster, more efficient web applications. Understanding the mechanics of the VDOM provides valuable insight into React’s inner workings and empowers developers to write performant and maintainable code.

--

--

Isuru Dinusha
Isuru Dinusha

Written by Isuru Dinusha

0 Followers

I am a software engineer specializing in front-end development.

No responses yet