What Makes React so Fast?

Austin Buhler
The Startup
Published in
4 min readNov 12, 2020

The Problem

DOM Manipulation is the heart of the modern, interactive web. Unfortunately, it is also a lot slower than most JavaScript operations.

This slowness is made worse by the fact that most JavaScript frameworks update the DOM much more than they have to.

As an example, let’s say that you have a list that contains ten items. You check off the first item. Most JavaScript frameworks would rebuild the entire list. That’s ten times more work than necessary! Only one item changed, but the remaining nine get rebuilt exactly how they were before.

Rebuilding a list is no big deal to a web browser, but modern websites can use huge amounts of DOM manipulation. The more UI components you have on your page, the more expensive the DOM updates can be, since they would all be re-rendered on every DOM update.

To address this problem, the team at React popularized something called the virtual DOM.

Virtual DOM

Like the actual DOM, the Virtual DOM is just a node tree that lists elements and their attributes and content as objects and properties. When new elements are added to the UI, a fresh virtual DOM is created with each element being a node on the tree.

When you render a JSX element, every single virtual DOM object gets updated. This may sound inefficient, but the cost is insignificant because the virtual DOM can update so quickly. (the virtual DOM can produce 200,000 nodes/second).

React and the VDOM

After a state change to any of your elements and creation of a fresh virtual DOM tree — this tree is compared or “diffed” with a snapshot of the previous DOM that was taken right before the update.

In React, render() is the point at which the UI gets updated and rendered but is also the point where this tree of elements is constructed. When a state or prop within a component is updated, render() will return a fresh tree. Same process with a setState() call.

React keeps their logic for what triggers re-renders incredibly simple — if a node is found to be different (whether that’s because the type is different or the component is different) it will re-render the entire subtree.

Once the comparison is done (more on this below) and React knows exactly which virtual DOM nodes have changed, those same nodes are then updated in the real DOM (but only those specific nodes that changed and not a full re-render).

In the example earlier, because React leverages the VDOM it’s smart enough to only rebuild the single checked-off list item and leave the remainder of the list untouched. React’s reputation for performance all stems from this ideal.

Diffing Algorithm

But how does React actually compare the trees and find the changes to insert into the real DOM?

After the trees have been constructed, React then “diffs” or checks for changes against the old tree. Their diffing algorithm is actually incredibly simple and based on the following two assumptions:

  1. Two elements of different types will produce different trees
  2. You (the developer) can hint at which child elements may be stable across re-renders with a key prop
source: https://www.oreilly.com/library/view/learning-react-native/9781491929049/ch02.html

If the root DOM element is different , it completely tears down the old tree and begins from the root of the new tree. On the contrary if the root DOM element is the same, then the algorithm compares each and every difference in attributes, keeps the same valued attributes and changes only the new/changed attributes.

Next, when an element contains multiple child nodes (i.e. a series of <li> elements), React will check for differences at the same time step by step. If the only differences in the child nodes are at the end, then that addition will be noted as the only update but if an element is added at the beginning all the subsequent children will also be flagged to update. In order to solve for this, React implemented a key attribute which it leverages to match up the children when running the comparison.

The last piece that increases React’s performance is that it actually compiles a list of all these changes necessary to the DOM and then batches them. This is done to avoid the browser’s DOM from triggering a re-painting of the UI, as this is the most expensive and inefficient part of DOM updates. Instead of sending updates for each single change in state, these are sent over to the DOM in one batch to ensure that re-painting event is only performed once.

React has intentionally chosen to keep their algorithm this simple in order to optimize for time efficiency while still keeping performance at a nearly identical level to some of the state of the art algorithms. They note that while those algorithms could lead to small performance gains they have a complexity somewhere in the order of O(n³) vs. their simple algorithm’s linear time — O(n).

Recap

To recap, manipulation of the browser DOM is not inherently slow, it’s their painting of the UI that is costly. React’s virtual DOM helps to minimize these painting events by making sure only the elements that need to be changed in the DOM are manipulated, and that these updates are sent in batches. These batches of updates prevent unnecessary “slow” painting events and make React applications more efficient.

--

--

The Startup
The Startup

Published in The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +772K followers.

No responses yet