Improve your React app performance using React Profiler
Recently, I was trying to improve the performance of a page in our React app, and I quickly suspected unnecessary re-renders to be the main issue there. After some investigations, I stumbled upon the React DevTools profiler plugin:
More particularly, I discovered a kind of hidden option of this plugin: being able to know why a component rendered. I found this feature so useful that I decided to create this article to share how to use it!
- Use React ≥ 16.5 in DEV mode
- Have React DevTools as an extension for your browser (Chrome or Firefox)
Improve a basic app with React Profiler
First of all, here is how to enable this option in your DevTools:
Now, let’s take the example of this simple application where you can see your goals of the day and set them as done. Let’s use React profiler to generate a profile and check what happens in our application after we click on the “Set as done” button.
“The color of a bar indicates how long the component (and its children) took to render in the selected commit. Yellow components took more time, blue components took less time, and gray components did not render at all during this commit.” (source)
We can see that all the “Goal” sub-components were re-rendered. Ideally, as we only updated the Goal “Read 30 min” we would expect that only this
Goal component would be re-rendered, not the other
How can we fix this? Now is the time to take advantage of the option we selected earlier to know why a component rendered! Let’s hover the first Goal component in the profiling data:
So the cause is that the property
setAsDone has changed. Let’s fix this quickly:
Thanks to that change, the method
setAsDone won’t change at each render of the
Goals component. Unfortunately, that won’t be enough here to prevent the re-render of the other
Goal components. Here is what the profiling data tell us now:
Goal components re-rendered because
Goals component re-rendered. And
Goals component re-rendered because “Hook 1 changed”, which is not very explicit right?
To know what this “Hook 1” is, let’s switch to the “Components” tab and the DevTools will smartly show you the right component:
We can now see that "Hook 1 changed” actually means "the state
goalsReached changed” which is indeed the case as we added the goal “Read 30 min” in this state.
In this specific case, we could use
React.memo to fix our issue (it might not be the best solution in every case of course, but let’s keep things simple for this example).
“If your component renders the same result given the same props, you can wrap it in a call to
React.memofor a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.” (source)
Let’s profile our app one more time:
We can now see that only the right
Goal component was re-rendered, while the others were not 🥳
That should help you in some of your investigations to improve the performance of your React app! Feel free to ask your questions or share your experience and tips with React Profiler in the comments!