How React Uses Diffing to Efficiently Rerender UI

Daniel Pericich
4 min readDec 30, 2020

With the rise of APIs, client side rendering has become a norm for modern web development. Angular, React and Vue are some of the most popular front end frameworks that allow for easy SPA development and browser side rendering. React is a very fast and lightweight Javascript framework that uses a diffing algorithm to efficiently rerender the UI as additional API calls are made and parts of the UI update and change.

In this article I want to go over the assumptions of the React diffing algorithm and special mechanisms built into it to help it correctly identify and rerender UI components. Knowing these things will help you write more efficient code.

What is Diffing in React?

Before we dive into how React’s specific diffing algorithm works, let’s first answer the question “What is diffing?” Diffing is the process of comparing two files to determine where and how they differ. If you have ever used a version-control system, such as Git, you are familiar with how the process of diffing is used to efficiently manage the changes and corresponding change log for a document as it is developed.

When you first commit (save) a file with Git, you commit the entire file to your repository (project folder). As you work on the file and commit your changes, you do not save an entire new copy of the file, you only save a copy of what has changed between the original and current copy. This saves you space by only saving the information that is new.

React uses the same general diffing concept in that on first render, React will load all parts of the page. As you make more calls to an API, or the user interacts with the page, React will compare the original page with the new page that is being called and only rerender the parts of the page that differ.

Now that we know what diffing is, what are the specific rules of React’s diffing algorithm?

How React Knows What to Diff?

Software engineering is a constant battle of tradeoffs between space and time constraints. React’s diffing is no different. While there are algorithms that can guarantee the least number of rerenderd components, these algorithms run in O(N³) time and thus lose any space gains with the enormous time demands. React uses two general conditions to rerender pages and components in O(N) time. The general conditions for rerendering are:

1) Two elements are of different types

2) There are no matching key props between compared child elements

The first thing React looks at when diffing components is the root element. If the root element is different React will automatically rerender the entire component’s DOM. If subcomponents’ elements are of different types then React will rerender those elements as well.

If the element types differ between UI’s, React will automatically rerender the element even if the content is the same. When React is diffing, if a element is the same type, but one of its attribute changes, React will only update the attribute.

Recursing on Children

The second condition occurs when React recurses on child elements that do not have shared key attributes. Child elements often occur as arrays that are iterated over and can be updated with insertions or deletions at any point in the array.

When recursing on the children of a DOM node, React does not try to match different elements. React simply runs diffs on the list checking if the same elements appear in the same order. For pushing to an array this will not affect performance, but if elements are inserted at or near the beginning of the array, this can cause the worst rendering performance. Even though all of the items but one are the same, React will change all of the elements instead of just updating the single new child element.

A solution to this issue is the key attribute. React gives users access to a key attribute which allows React to match elements between different trees. React keys can be given any value unique between the child elements. Keys only have to be unique with their siblings, not globally. Some properties of a good key are:

1) Keys are stable — they don’t change throughout the life of a component

2) Keys are predictable

3) Keys are unique between sibling elements.

A last resort for key values is to use array indexes, but this is not a great idea as insertions anywhere besides the tail will cause the tree to rerender unnecessarily as all the array’s indexes are updated.

Final Thoughts

Client side rendering allows for API integration on a number of devices which streamlines web development. Knowing the ins and outs of how your framework of choice handles rerendering the UI can lead to big performance gains and better overall readability in your code!

Sources

https://reactjs.org/docs/reconciliation.html#recursing-on-children

--

--

Daniel Pericich

Former Big Beer Engineer turned Full Stack Software Engineer