How React Works Under The Hood

Zainab JINARIZainab JINARI
6 min read

Introduction:

In this tutorial, we will explore how the React framework works. To achieve this, we'll start by understanding the traditional way of doing things. We'll use an example to see how it is rendered and discuss the performance limitations of this model. Then, we'll introduce React and focus on how it operates. We'll cover the virtual DOM, reconciliation, diffing algorithms, and other key concepts in the React ecosystem.

Understanding The DOM and UI Rendering

Before diving deep into understanding React, it’s crucial to grasp the necessity of creating such a framework. Therefore let’s take a quick example to illustrate how things worked before React, using vanilla JS.

<html lang="en"> 
    <head> 
        <meta charset="UTF-8"> 
        <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
        <title>Pre-React Example</title> 
    </head>
    <body> 
        <h1 id="heading">Hello, World!</h1> 
        <button id="changeTextBtn">Change Text</button> 
        <script> 
            const button = document.getElementById('changeTextBtn'); 
            const heading = document.getElementById('heading'); 
            button.addEventListener(
                'click', 
                function() { 
                   heading.textContent = "Text Updated!";    
                }
            ); 
        </script> 
    </body> 
</html>

This example shows how we can change the content on a webpage using a button with some JavaScript code. Let's explore exactly how this process works.

When this HTML file gets received by the browser, the parsing process begins here is where all the magic happens :

\=> The browser reads from top to bottom: let’s say the first tag which is the html tag will create a variable in memory which will represent this particular tag and it will hold an object containing all the attributes of this node in this case the lang attribute. So it will look something like this:

root:{
    title:'html',
    attributes:[
        'lang':'en'
    ]
}

Note: this is just a very simple way to illustrate it

Linking each node to its descendants once the browser creates a child node, resulting in a tree-like structure which is what we call the DOM Three.

💡 DOM: short for document object model, which is the representation of the webpage as a variable in memory.

\=> By the end of the HTML parsing we get a tree-like structure stored in memory which represents the UI rendered to the user.

\=> When the browser encounters the script tag at this stage the tree has already been built, the JS engine has to start executing the script now.

\=> The script starts by interacting with an object document which is what holds reference to the root of the tree structure in memory. Using this object and the various methods provided you can make a tree search for an element using the getElmentById,querySelector, or other methods offered by the object.

❓The problem faced at this stage is that manipulating this object and making changes to it has a high cost as it’s time-consuming and resource-intensive. Why ??

💡 Well, to make it sync let’s continue our talking about the process of rendering the UI, after completing the parsing, and creation of the DOM Tree (as well as the CSSOM Tree which is where all the style is stored we will not dive deep into it in this tutorial ).

\=> The browser creates what’s called The Render Tree, which is the result of combining the DOM, and the CSSOM tree. This one holds only visible elements and the styles that apply to them, in our example, it’s what’s inside the body tag. Each node of this tree contains the computed style (the resulting style after calculating inheritance and the overridden rules) and the geometry which is where the element is going to be placed in the UI.

\=> Once the render tree is built another process takes place, this one is called the Reflow or Layout Phase based on the calculations made earlier in the browser calculates the position and the size of each element how much space should be between each element and the other taking into account the viewport and CSS styles calculated before

\=> Last but not least the browser gets to The painting Phase which is essentially the drawing of the virtual representation of the layout, at this stage, we get to see the colours, shadows, borders and texts that are present in the layout (before it was like the empty wireframes and in this phase we get to see the actual design this is how I illustrate it )

\=> Finally, the browser does the Composing which is the creation of other layers to apply styles for instance z-index or absolute positioning.

🤔 Now that we understand the flow of the whole process it's easier to deduce why the intensive repetition of this process has a high cost.

React and React Render System

💡React comes to solve this problem for us and makes our lives easier by introducing a new concept called Virtual DOM.

To fully grasp this concept let’s take our first example and represent it in a react-like way and see the differences that will occur in the render process.

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

const App = () => {
    // Declare a state variable 'text' with initial value "Hello, World!"
    const [text, setText] = useState("Hello, World!");

    // Function to change the text when the button is clicked
    const changeText = () => {
        setText("Text Updated!");
    };

    return (
        <div>
            <h1>{text}</h1>
            <button onClick={changeText}>Change Text</button>
        </div>
    );
};

// Render the App component to the DOM
ReactDOM.render(<App />, document.getElementById('root'));

So with this refined version provided by React, the process will go as follows :

\=> When a user click the button the useState hook will get triggered which will make the value of the text variable change.

\=> Once the state of the component changes, it’s marked Dirty which refers to the necessity of re-rendering it.

\=> This is when React creates a new virtual DOM which will look something like this :

const virtualDOM = {
    type: 'div',
    props: {
        children: [
            {
                type: 'h1',
                props: {
                    children: 'Hello, World!',
                },
            },
            {
                type: 'button',
                props: {
                    onClick: someClickHandler,
                    children: 'Change Text',
                },
            },
        ],
    },
};

\=> Reconciliation: this is when React takes the new VDOM and the old one and compares them using an algorithm called Diffing Algorithm (the way the comparison works will not be covered in this tutorial as it’s out of this scope and more complex). => Once the output gets returned, the changes get detected React apply changes only to necessary parts of the Real DOM which prevents it from rerendering the whole tree and going through the intensive process.

Conclusion:

React transforms UI development by overcoming the performance issues of traditional DOM manipulation. The Virtual DOM optimizes rendering, updating only necessary parts of the real DOM, reducing computational costs and improving efficiency. Understanding React's mechanisms, like reconciliation and the diffing algorithm, highlights its performance advantages. This enables developers to build dynamic, responsive applications easily. Follow for more React content and feel free to comment if you need clarification. Your feedback is welcome!

10
Subscribe to my newsletter

Read articles from Zainab JINARI directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Zainab JINARI
Zainab JINARI

A full-stack engineer and passionate website designer, experienced in creating projects from scratch. I’m in my 5th year studying Web & Mobile Application Engineering, and I’m also an enthusiast of AI and blockchain technologies. As a full-stack engineering student, I thrive on developing end-to-end solutions, from design to deployment..