All you Need to know about Virtual DOM
As a web developer, you may have come across the term called DOM many times. Furthermore, while working with JavaScript Library like React, you may have heard of one buzzword and that is Virtual DOM. This article will explain all you need to know about Virtual DOM. This will help you to uplift knowledge about core React concepts.
Before diving into Virtual DOM, let’s understand some basic terminologies first.
DOM
The DOM (“Document Object Model”) is a standard specified and documented by W3C (World Wide Web Consortium). It defines a standard for accessing documents like HTML, XML:
“The W3C Document Object Model (DOM) is a platform and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of a document.”
In context to HTML Document, the above definition says that DOM allows you to manipulate the content, structure, and style of your UI. DOM is a tree structure representation of HTML Document where root node represents the <html> element itself. All elements of the HTML document become child nodes subsequently.
When you load the HTML document in the browser, it creates and maintains its document object model of the page by constructing a DOM tree of HTML elements.
As shown in the example image, right-click on the web page and click on Inspect property to access the DOM Tree. Every time you make some changes in UI, the browser would repeat Reflow and Repaint all changed DOM tree nodes and their children in order to reflect the changes you made in your UI.
This process of changing UI and making frequent updates in DOM may cost the performance of UI. It may also affect the page rendering and page load time. If your page is large and has a complex UI structure, it can be a very visible lagging in the loading of the page.
For instance, Let’s create an HTML page that has a list element with some listed values. Now we are adding more elements to this list using JavaScript as shown below.
As demonstrated, we can update the list element in UI by manipulating the DOM object directly. This snippet shows that when we are adding a new list element, we are appending a new child element to the DOM which results in creating a whole new list element in UI.
Every time when we make changes in the list, DOM creates and updates a new List to DOM. These DOM manipulations are very expensive operations and it also impacts UI performance, especially for large-scale or complex UI applications.
Virtual DOM in REACT
To conquer the above-mentioned drawbacks, in every DOM there is a corresponding virtual DOM (VDOM) in React. Virtual DOM is an object identical to the JavaScript Object. In other words, Virtual DOM is simply a programming concept or a representation of a DOM object in memory as a virtual form. Virtual DOM has the same power and properties and methods as the real DOM object. But Virtual DOM is not directly responsible for displaying elements on UI.
When React App gets rendered for the first time on the browser, it basically creates a fresh copy of the DOM object as a render tree along with a Virtual DOM in memory for future updates. Later when a component gets updated due to state or props changes, the component and its children get re-rendered. While Updating Virtual DOM, React takes a snapshot of Virtual DOM at each time just before updating Virtual DOM. Now one contains the updated Virtual DOM and one which is just the updated version of this updated Virtual DOM. Now it compares the updated version with the updated Virtual DOM and works out the changes for instance what part of UI has been changed in the DOM. To update UI, React syncs the actual DOM object with Virtual DOM which is stored in memory using a library such as ReactDOM. This process is called Reconciliation.
Basically, DOM updating for every in the React App requires comparisons between actual DOM and a Virtual DOM stored in memory. Though the comparison process ends with a new copy of the DOM tree, In a generic way React has to process O(n³) number of operations to transform one tree into another. In the case of complex apps, these comparisons are far too expensive.
Instead, React implements a heuristic O(n) algorithm based on two assumptions:
- Two elements of different types will produce different trees.
- The developer can hint at which child elements may be stable across different renders with a key prop.
The Diffing in React
Now React use the heuristic approach and implement Diffing Algorithm to update components optimally.
Elements Of Different Types
As we discussed, after first rendering, Virtual DOM creates a copy of the DOM tree in memory. In subsequent updates, Virtual DOM creates a snapshot of the render tree and checks, If the root element of the render tree is different, it completely tears down the old tree and begins from the root of the new tree.
During this update, old DOM nodes are destroyed. Component instances receive componentWillUnmount(). When building up a new tree, new DOM nodes are inserted into the DOM. Component instances receive UNSAFE_componentWillMount() and then componentDidMount(). Any state associated with the old tree is lost.
Elements Of The Same Type
Once the component with the same type is updated, then the algorithm compares each and every attribute of the element. It compares and keeps the same valued attributes and changes only the new/differed attributes.
When the component with the same type gets updated, the same instance is maintained, so that state is maintained across renders. React updates the props of the underlying component instance to match the new element, on the underlying instance.
Next, the render() method is called and the Diffing algorithm recurses on the previous result and the new result.
Updates in Child Elements
When React finds any change in child elements, it just compares and calculates which children changed and updates it using Diffing algorithm as we have seen above.
In above example, List element gets changed when we add new list item <li>Orange</li>. React match each child of <ul> and finger it out mutation in the list. Insertion of this list item at the beginning of the list will impact and it can worsen the performance here. React will mutate every child instead of a newly inserted item. To resolve this issue, we should use a key attribute. React uses the key to match children in the original tree with children in the subsequent tree when each child has been assigned a unique key value. For instance, adding a key to our inefficient example above can make the tree conversion efficient:
Conclusion
So, to summarize, we have understood the basics of virtual DOM and its insights. We have seen that frequent DOM manipulations are expensive. Reconciliation is a process where Virtual DOM is a DOM representation in memory that is in sync with Real DOM. React use the Diffing algorithm to compare Virtual DOM and preupdated Virtual DOM to update DOM.
- https://developer.mozilla.org/en-US/docs/Glossary/DOM
- https://reactjs.org/docs/faq-internals.html#gatsby-focus-wrapper