6 Oct 2021
How to Detect Slow Renders in React?
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 do we detect these bottlenecks?
Profile the problem
Open the React Developer Tools 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.
Analyze the results
Find a slow commit you want to improve. You can see the commits bar in the top right corner of the profiling results. For more information on commits, check out React Docs - Browsing Commits.
In our case, the 1st, 2nd, and 4th commits are slow. They take more than 300ms to render. Any 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).
Now let's pick one of these commits and check the "Flamegraph" to see what's causing this poor performance.
The Flamegraph shows our component tree. We can see that the Home
component and its entire sub-tree re-render. The SearchResults
component responsible for the main UI change is pretty fast and takes only 7.4ms to render. The SlowComponent
takes up most of the rendering time. It is the bottleneck.
Fix the bottleneck
Let's look at the code of the SlowComponent
:
We can wrap our expensive calculation with useMemo
to ensure it only runs when necessary. Since we don't rely on any props, we can leave the dependency array empty. This way, our expensive calculation won't be re-triggered every time SlowComponent
re-renders.
Now let's analyze the performance again.
The UI feels faster already. Let's check the commits.
The 1st, 2nd, and 4th commits are still the slowest. But now they each take around 12-17ms to render, which is 14 times faster than before. Let's analyze the Flamegraph to see what happened.
The SearchResults
component now takes the most time to render. But since it's only 12ms, we have nothing to worry about. And now that we've put our memoization in place, the SlowComponent
takes only 0.3ms to render.