DOM Manipulation in React
In this article, a developer explores how DOM manipulation works in React.js's Virtual DOM and how it improved upon standard DOM manipulation.
Join the DZone community and get the full member experience.
Join For FreeIntroduction
DOM stands for Document Object Model. It is an in-memory representation of HTML and is tree structured. DOM Manipulation is the process by which one can dynamically change the content of the web page. Normally, JavaScript is used while working with the DOM. Methods like getElementById
or removeChild
are part of the API provided by the HTML DOM.
The Issue
DOM Manipulation is the core of modern interactive web pages. So, it is important that working with DOM should be fairly easy and quick. Since, it is always tree-structured, traversing the DOM is easy. But when it comes to the quick part, it is not as quick as it should be.
For example, let us say we want to update the first item of a list containing ten items. Most JavaScript frameworks would update the entire list, just to update only the first item. Most modern web pages have huge DOM structures and this behavior would cost too much, resulting in slower loading pages.
To counter this problem, React popularized something called the Virtual DOM.
The Virtual DOM
The Virtual DOM is a copy of the HTML DOM and is local to React. We can call it an abstraction of the HTML DOM. So, whatever changes need to be made to the DOM, React does that to this Virtual DOM and syncs the Real DOM accordingly. This process is called Reconciliation.
Once you render a JSX element, every single Virtual DOM object gets updated. One may doubt that it is efficient to update the entire Virtual DOM. But compared to updating real DOM objects, the Virtual DOM updates faster. Before updating, a copy of the virtual DOM is made and later compared with the updated Virtual DOM. Then React can figure out which objects have been changed, and this process is called Diffing. Once React knows which objects to update, it updates only those objects in the Real DOM.
So, in our previous example, React will only update the first item on the list, leaving the rest of them as is. Isn’t that efficient?
Behind the Scenes: Rules
So, now we know how React updates the HTML DOM objects using the Virtual DOM efficiently. But what really happens behind the scenes? Let us look into the algorithm which React uses for this purpose. It is the Diffing Algorithm.
Diffing is nothing but comparing two trees, in this case, the Virtual DOM before updating and after updating. The behavior is different depending on the type of root elements. Let us look at some of the rules of this Algorithm.
Different Element Types
If the root elements of the two trees are of different types, React will rebuild the entire tree again. Consider the below example:
<div>
<Tree />
</div>
<span>
<Tree />
</span>
The root elements of the two trees are div
and span
, which are different. Hence React will tear down the tree, and rebuild the entire tree again. The child elements, Tree
in this case, will also be unmounted and get its state destroyed, and React will remount it again.
Same Element Types
When both the elements, which are compared, have the same type of elements, then React will look into the attributes. Then it’ll only update the attributes, if necessary, leaving the element as it is. For example look at the HTML snippet below:
<span id=”span1” />
<span id=”span2” />
Here, since the elements are of the same type (span
), React will check the attribute id and will update only if there is a difference.
When the Root elements are handled, React will then look over the children recursively.
Comparing Child Elements
Let us take an example and explain how React compares two lists.
List1:
<ul>
<li> Child1 </li>
<li> Child2 </li>
</ul>
List2:
<ul>
<li> Child1 </li>
<li> Child2 </li>
<li> Child3 </li>
</ul>
Here, a new child <li> has been added to the end of the list. Now, React iterates over both lists and inserts the third child to the DOM. It matches every child, and if there is no difference, moves to the next, and generates a mutation, when there’s a difference. But this is fine as the new child is added to the end of the list. A problem arises when the new element is added at the beginning of the list. For example:
List1:
<ul>
<li> Child1 </li>
<li> Child2 </li>
</ul>
List2:
<ul>
<li> Child3 </li>
<li> Child1 </li>
<li> Child2 </li>
</ul>
Now, React compares the first elements and finds that there is a difference and the element is mutated. The same happens to the next elements as well. So, without knowing it, it is rebuilding the entire list again. This reduces the performance when compared to adding the child at the beginning of the list.
To solve this issue, React supports an attribute, Key.
Comparing Keys
If the attribute key
is added to the child element, React compares the values in key
of the first tree, and matches it to the key
value in the second tree.
Example:
List1:
<ul>
<li key=”101” > Child1 </li>
<li key=”102” > Child2 </li>
</ul>
List2:
<ul>
<li key=”100” > Child3 </li>
<li key=”101” > Child1 </li>
<li key=”102” > Child2 </li>
</ul>
Here, React will know that a new child element with key="100"
has been added to the list, and the rest were moved down. Hence, it’ll not rebuild the entire list again. This will improve the performance of DOM Manipulation.
Conclusion
Although there are many JavaScript frameworks that are both popular and efficient, React takes the cake when it comes to DOM Manipulation efficiency. To summarize how React updates the DOM:
- React will update the entire Virtual DOM.
- It’ll then compare the Virtual DOM before updating, with the one after updating, to identify what objects have been changed. It uses the Diffing Algorithm.
- Only the changed objects will get updated on the Real DOM.
Published at DZone with permission of Naveen Kosana. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments