removeChild are part of the API provided by the HTML DOM.
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.
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
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.
<ul> <li> Child1 </li> <li> Child2 </li> </ul>
<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:
<ul> <li> Child1 </li> <li> Child2 </li> </ul>
<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.
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.
<ul> <li key=”101” > Child1 </li> <li key=”102” > Child2 </li> </ul>
<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.
- 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.