Published in November 04, 2020

ReactJS Virtual DOM

What is It and How Does It Work?

ReactJS is a JavaScript library for building user interfaces. It is a component-based library that encapsulate your code in a component. Data can be passed into components, each component is specific and can manage it own state for storing data. The state is separated from the DOM. Components are rendered and its data is updated when the there is a change in the state.

Virtual DOM

Unlike other libraries, ReactJS builds a virtual representation of DOM element. This is a tree of JavaScript objects that represent the browser DOM.

ReactJS doesn’t allow manipulation of the browser DOM, Instead you manipulate the virtual DOM which then result into the browser DOM.

Why Virtual DOM?

The reason for a virtual DOM is to enhance and optimize update to the actual virtual DOM.

In vanilla JavaScript, you manipulate the DOM using the typical DOM API selector, like document.getElementById or document.querySelector to select an HTML tag, and you can modify the tag using properties like .innerText, innerHTML, or .value.

Although DOM manipulation is faster this way, it is still problematic because:

  • DOM changes cause browser to reloaded. This is inefficient.

  • Recalculating and rendering layout after manipulation is slow

The virtual DOM is node tree of element and attributes just like the browser DOM. The node tree is created by React’s render() method from React components in response to change in React’s data model.

When there is a change, the render() method recreates the entire DOM, resulting to a new virtual representation of the DOM.

This involves a three-step process that optimizes the performance and makes the virtual DOM fast:

  • It re-renders to new virtual DOM when there is trigger of change in the UI.
  • The difference from the old virtual DOM and the new one will be recalculated to see what has changed.
  • The browser is updated from the virtual DOM with what has changed.

Updating the actual DOM with new data from the virtual DOM without reloading the browser is not only efficient but ideal. Although, it may seem like the virtual DOM would/should be slow because of the double render, and diffing to see what has changed. The fact is that rendering the virtual DOM is more efficient than rendering UI in the actual browser DOM.

Virtual DOM Object

First thing to know is that all elements in the virtual DOM are a function of ReactElement.

ReactElement

ReactElement is representation of DOM element in the virtual DOM. This is what is then put in the “actual DOM” of the browser.

To understand how this works, you need follow along with code samples you can modify and test. Download code sample from here. Follow the instructions and open the reactjsvdom/index.html file in your browser and code editor.

The HTML file is the default template that will show all rendered virtual DOM in the browser. It has a <div> element to contain the rendered DOM and after it is the <script> tag pointing to the script source file.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>React's Virtual DOM</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script src="./vdom.js"></script>
  </body>
</html>

Open the reactjsvdom/vdom.js in your code editor. This is the react component that the <script> tag above is pointing to. We will write all react code here.

Now let create an element and add (render) it to the browser DOM. To create an element use the createElement method.

// Create virtual DOM element
const headerTag = React.createElement("h1")

The method creates a virtual DOM of <h1> header tag that will be turned into browser DOM tree. The headerTag is an instance of ReactElement. This is how to create ReactElements implicitly without using JSX.

The element has only been created, but not rendered to the browser DOM, let do that next.

Render ReactElement.

To render elements created by the createElement() method, the render() method is used. The method takes in two arguments:

  • The virtual Element to render.
  • The HTML tag to mount rendered Virtual DOM (the div with id of root in the HTML template).
//...

// Access HTML tag with id of "app"
const mountTag = document.querySelector("#app")

// Render headerTag into the DOM tree
ReactDOM.render(headerTag, mountTag)

NOTE:

The only time you directly access the browser DOM is when getting the HTML tag to mount rendered ReactElements

A new html element has been inserted as the child of the div element in the browser DOM. Nothing is showing on the browser because we only added an empty tag without any text in it. To view the tag, right-click on your browser and click on “inspect” to open the developer tools window. click on “Inspector” if you use Firefox or “Elements” if you use Chrome to inspect the HTML document. Expand the div tag and you should see the h1 as a child tag.

Screenshot image

Click on image

Add Text(child) To Tag

We’ve rendered and mounted and empty tag, now we’ll add a child element of text to the h1 tag. To add a child element the createElement() method will be updated with other arguments added to it.

The createElement() method takes in three arguments in all, namely:

  • The DOM element type
  • The element props
  • Children of the element

Let’s walk through this arguments.

  • The DOM element type is the HTML tag you want to be mounted in the browser. This will act as a parent element to other element that are mounted under it.
  • The element props is how react passes arguments or attributes to its component. If we had another component then we could pass in data from it as props to the current component. we’re not passing props so it’ll be left as null
  • The children DOM consists of ReactNode(virtual representation of real DOM nodes) objects:
    • ReactElement
    • ReactText object (string)
    • An array of ReactNodes

To insert text in the h1 tag, we’ll pass in string as the third argument in createElement() method

// Create virtual DOM element
const headerTag = React.createElement("h1", null, "Hello World!")

//...

Screenshot image

Click on image

The render() Method

We know that the render() method mount the virtual node tree in the actual browser DOM. But you might not know it also accepts a third callback argument that runs after the DOM is mounted. This can be used to run side-effects after the virtual DOM has mounted.

//...

// Render virtual node then run callback
ReactDOM.render(headerTag, mountTag, () => alert("Think before reacting!"))

NOTE:

To run side-effects in React use lifecycle methods, or the hook method useEffect() introduced in version 16.8.

Conclusion

The virtual DOM makes updating the browser with changes in the data model easier than in other UI libraries. This boost performance by optimizing UI. With that said, as a developer, If working with another library other than ReactJS does the job well for you then stick to it. “A tool is only as good as the person using it.”

Thank you for reading 🙏🏿


Hi, my name is Romeo Peter. I'm a self-taught software developer and blogger --- I build web application, and automate business processes. I don't know it all, but what I do know, I manage to share for others to learn.

Follow me on Twitter. I share my thoughts there.

I'm available for work. Contact me to work on a project or work with you. I usually get back immediately.