Engineering Blog

React’s Reconciliation Algorithm

Overview

The “reconciliation” algorithm in React is how the decision to re-render the component is made. In the browser, DOM manipulation is expensive and time consuming, both in mounting and unmounting. Part of what makes React very performant is its reconciliation algorithm.

In short, it watches closely for differences, and only updates the DOM when necessary and tries to update only the parts which need to be changed.

The “Virtual DOM”

The Virtual DOM is a theoretical DOM tree generated by React when a change is made to a component’s state. This is modeled after the state of your application upon modification of the state, for example, after calling this.setState(). React uses what is called a “snapshot” to make this comparison and analysis between the DOM before the update, and the DOM after. This is the point in time when React utilizes its reconciliation algorithm.

Updating the Virtual DOM is much faster than the real DOM, since the browser doesn’t need to show a visualization of it.

How updates are determined

The reconciliation algorithm is run whenever the component level state is updated. It analyzes the current DOM with the Virtual DOM, in order to determine which changes need to be made to the real DOM. After this step, it has determined which DOM nodes on your application require updates, and it calls the render method.

Here is a simplified visual depiction of a Virtual DOM diff on an unordered list within a div.

Effect on DOM elements and their attributes

The reconciliation algorithm does not only look at whole DOM elements, it also looks at individual attributes. You can think of the difference as a PUT request vs. a PATCH request, where it only updates the parts which have changed, rather than updating the entire object if there was a change.

While it doesn’t unmount and remount the entire element if it doesn’t have to, sometimes it does have to. An example of this would be if you render an element of a different type.

Suppose you wanted to switch between two components or elements, perhaps for conditional rendering. This would result in a full unmounting of the component, regardless of whether or not they contain the same child nodes.

This differs from switching attributes on the same type of elements, an example of which might be dynamic class names, based on component state. In this scenario, the DOM element is not destroyed, and only the modified attributes are changed. This is useful because it performs minimal operations on the DOM, which as we know, is more resource-intensive than standard object operations.

Keys and rerenders

The “key” attribute in React can be used to mark whether or not a DOM node is stable. You may have seen a message in the console if you’ve ever attempted to map over a collection and return a JSX element each iteration. This is because the reconciliation algorithm uses the keys to determine if the content has changed, and not including a key may cause unexpected behaviour. For this reason, the keys should be unique so that reconciliation can recognize and identify which elements are stable, and which elements are not.

Suppose that you have a list of items, which is derived from an array. If you were to splice an item into the middle of it, that will change all of the indices of the subsequent items. In this scenario, since the keys will not be a stable, unique representation of each item, React can end up mutating the unintended item, which can cause major bugs.

A detailed explanation of keys can be found on the official React docs:

https://reactjs.org/docs/lists-and-keys.html

https://reactjs.org/docs/reconciliation.html#keys

For an in-depth exploration of how and why reconciliation was implemented, please visit the official React docs:

https://reactjs.org/docs/reconciliation.html

Related Posts