Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Profiling Performance with React Developer Tools

Jun 5, 2020 • 9 Minute Read

Introduction

Profiling the performance of a React app can be a difficult and time consuming process. By installing the React developer tools, you can record and interrogate the performance of individual components in your app and make this process much easier.

The guide will be based on a React web app, however, the developer tools can also be used with a React Native app. The app used in the examples below is here.

Installation

The first thing to do is install the developer tools. How you do this depends on the browser you are using to run the app. For Chrome and Firefox, the developer tools are available as browser extensions and can be found in the appropriate extension store. If using a different browser, the developer tools can be installed as a standalone app from this npm package.

Once developer tools are installed in either the standalone app or the browser, two new tabs will be available: Components and Profiler. This guide will use the Profiler tab.

Profiler Tab

This is an example of a chart showing each commit that occurred during the profile recording:

Hover over a commit to get information on its duration and at what point in the recording it occurred, and select a commit to view it in the other charts.

Flamegraph

This is a flamegraph chart of a commit in the example app:

Each bar in the graph represents a React component, and the width of each bar represents how long it took to render the component and its children. The bars are also color-coded to help show at a glance which components took the longest to render, but the actual durations can be seen on the bar (if there is room for the text) or by hovering on the bar.

In the graph above, you can see that the AppContextProvider took the longest to render with a total of 8.7 ms. However, only 1.8 ms of that was taken up by the AppContextProvider itself, while the other 6.9 ms was its children rendering. If you then move to its only child, the Context.Provider component, you can see that its render took 0.4 ms, and the rest of the 6.9 ms was taken by its children, and so on down the chart.

As you move down the chart, it can become more difficult to see the components as they get smaller. Selecting a component will expand that component to the full width of the chart, making it much easier to see.

Ranked Chart

The ranked chart displays each component in the commit as a bar, but this time they are ordered by the duration of their render. This is a ranked chart of the same commit as the flamegraph above:

This chart deals just with the time taken by the component itself and doesn't show anything about how long the children took to render. If you are having a performance problem that is being caused by a single component, it should be very easy to identify using this chart.

Profiler Settings

There are two options on the Profiler tab in the developer tools settings menu:

Often, components are rendered that we don't expect to have been, and debugging why this has happened can be very difficult and time consuming. To help with this, the React developer tools can record the reason each component was rendered when recording a profile. Check the Record why each component rendered while profiling checkbox to use this feature. If this feature is selected, when a component is selected from either of the charts in the right hand panel, a reason will be displayed as to why the component rendered.

When profiling an app, you will sometimes produce a very large number of commits, and you will often only be concerned with those that take a longer amount of time. In order to reduce the clutter in the Profiler tab, you can set the Hide commits below setting, and only commits that took longer than the specified number of milliseconds will be shown.

Profile the Initial Render

Find a Performance Issue

The example app contains a performance issue. While the issue is very contrived, it can be used to show how to find an issue in an app.

In the example app, when clicking on the Show count buttons on the right hand side of the window, there is a noticeable lag before the count appears and the button label changes to Hide count. To try and identify the cause of this lag, you could record a profile of a user toggling the Show count and Hide count buttons a few times. This is a chart of the commits produced by showing and hiding three times:

You can see that commits 1, 3 and 5 are showing bars significantly higher than the others. This would be expected as the lag occurs on the show rather than the hide. Selecting any one of these commits shows a flamegraph and a ranked chart like these:

The first thing you see is that all of the components above the NumberSelector in the tree are showing with a grey background because they were not rendered in the commit; this is what we would expect as all of the state and event handling for this component is done locally.

It probably won't take too much time to see that this component contains a function, getCountToShow(), which is called every time the component is rendered with the showingCount state set to true. That looks like this:

      const getCountToShow = () => {
  pointlessDelay();
  return changedCount;
};
    

A good attempt to fix this performance issue might be to remove the call to pointlessDelay and then re-record a profile and see if the lag has disappeared both from the user's point of view and the profiler charts.

Conclusion

This guide has shown some of the tools that can be used to profile a React app and help identify performance issues. There is one more chart available in the profiler: the interactions chart. This uses an experimental API that is subject to change and would probably need a guide of its own to cover the functionality.

The code for the example app used in this guide can be found here.

Chris Dobson

Chris D.

Chris is currently working in the UK healthcare sector as an 'Expert Developer' and has been developing software both for fun and professionally for more years than he cares to remember. Having developed software for, among others, Unix, Win32, ASP .NET using C, C++, C#, and F# for the last few years has been using Javascript and Typescript to develop for Node and React and can't remember enjoying his job quite as much as he is at the moment. In his spare time if he is not spending time with his 5-year-old daughter Chris can usually be found playing cricket.

More about this author