How to Detect Slow Renders in React?
Tags: react, performance
Published: 2021-10-06 11:19:05

Improving React app performance often comes down to finding bottlenecks and fixing them. One well-placed memoization can make a slow app fast again. But how to find performance bottlenecks? 

---

## Profile the problem

Open [Rect Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) Profiler tab. Click the record button to start profiling. Interact with the part of your app that feels slow, then click the record button again to stop profiling.

![profile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tzerdjf2vt4crepokyuy.gif) 

---

## Analyze the results

Find a slow commit you want to improve. You can see the commits bar in the right top corner of profiling results. For more info on commits, check out [React Docs - Browsing Commits](https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html#browsing-commits).

![commits](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vomerelylltev9cul3w.gif)
 

In our case, 1st, 2nd, and 4th commits are slow. They take more than 300ms to render. Every response to a user action that takes more than 100ms breaks the connection between the action and the result ([RAIL: A User-Centric Model For Performance](https://www.smashingmagazine.com/2015/10/rail-user-centric-model-performance/#putting-the-user-in-the-center-of-performance)).

Now let's pick one of these commits and check the "Flamegraph" to see what is causing this poor performance.

![flamegraph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ng9ktriw0oha8pvouzqk.gif)
 

The Flamegraph shows our components tree. We can see that component `Home` and its entire sub-tree re-renders. The `SearchResults` component responsible for the main UI change is pretty fast and takes only 7.4ms to render. The `SlowComponent` takes most of the rendering time. It is the bottleneck.

---

## Fix the bottleneck

Let's look into the code of a `SlowComponent`:

```jsx
const SlowComponent = () => {
	
  // Expensive calculation that takes 300+ms
  const n = [...Array(3000000).keys()].reduce((p,c) => p + c)
  
  return (
    <p>Expensive calculation - {n}</p>
  )
}
```

We can wrap our expensive calculation with `useMemo` to make sure it only runs when necessary. And since we don't rely on any of the props, we can leave the dependency array empty. This way, our expensive calculation will not be re-triggered every time `SlowComponent` re-renders. 

```jsx
const SlowComponent = () => {
	
  const n = useMemo(() => {
    // Expensive calculation that takes 300+ms
    return [...Array(3000000).keys()].reduce((p,c) => p + c)
  }, [])
  
  return (
    <p>Expensive calculation - {n}</p>
  )
}
```

Now let's analyze performance again.

![profile-2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kgxno7zm7w466bgc6g80.gif)
 

The UI feels faster already. Let's check the commits.

![commits-2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vz2cu2ign33c0wwq89z4.gif) 

The 1st, 2nd, and 4th commits are still the slowest. But they each take around 12-17ms to render, which is 14 times faster than before. Let's analyze the Flamegraph to see what happened.

![flamegraph-2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e1y5nm6b1fi0srf8512w.gif)

The `SearchResults` component takes the most time to render now. But since it's only 12ms, we have nothing to worry about. And now that we put our memoization in place, the `SlowComponent` takes only 0.3ms to render.

---

Originally published at [alexsidorenko.com](https://alexsidorenko.com/blog/react-performance-slow-renders/)