Use the New Profiler in React Developer Tools to Generate Flame Charts and Interactions


September 10, 2018

Reading time
5 min read
The above video is hosted on

React version 16.5.0 has been released and one of the features that it supports is the new Profiler in the React Developer Tools. In the above video and following blog post, we will update an existing app to ⚛ React 16.5.0 and show off various features of the new Profiler. The tool will auto-record a lot of information from your React application, but you can also add interaction tracking to gain insight into user-generated events.


Before you can utilize the new Profiler feature of the React Developer Tools, you'll need two things...

  1. React v16.5.0+ (Developer Build)
  2. React Developer Tools v3.3.2+

NOTE: If you want to profile in production see the Profiling in Production gist from Brian Vaughn (@brian_d_vaughn).

Profiling Your Application

For this blog post, I'm using a copy of the Redux TodoMVC Example app from the redux repository. You can find the code for this video/post at

Empty Profiler Tab

Initially, the Profiler tab will look empty (see the following screenshot). To assess the performance of your application, you'll need to gather profiling data first. You can do this by clicking the ⏺ record button and then start interacting with portions of your application that you want to profile. Once you're done interacting with your app you can click the "Stop" button.

Initial Flamegraph after Gathered Data

Once you've gathered profile data, you'll immediately see Flamegraph data for the first render that occurred (see the following screenshot). For each render, you can see what components were involved and which ones took the most time to complete. The gray bars represent components that didn’t need to re-render at all (they could have been PureComponents or have implemented shouldComponentUpdate manually).

Single-Click to View a Component's Details

If you single-click on one of the components (like TodoTextInput for example) then the Flamegraph will zoom into that particular component tree (see the following screenshot) and the right panel will give more detail about that component including its props and state.

Double-Click to View a Comparison Across All Renders

You can double-click on an item (like MainSection for example) and see a comparison graph of how long it took across all renders. And then you can drill into one of the instances by double-clicking on it to see which render it was related to.

Ranked Flat View of Components

You can also look at a ranked flat view of the components from top to bottom. The items at the top took the longest and the items at the bottom took the least amount of time to render. This view can help when trying to make sense of all the data presented.

Tracking User Interactions

There is another view called "Interactions", but it’ll probably be empty by default. You have to add some code to your app before anything will show up here.

The point of interactions is to give meaningful names to user events. The idea is to associate a render in the Profiler based on the intent of what happened. For example, it'd be nice if we could see the render when a Todo item is being added or when one is being completed.

There's a nice gist describing the ins and outs of Interaction Tracking with React written by Brian Vaughn (@brian_d_vaughn).


To begin, you'll need to install the schedule package that contains a track function that we'll need to invoke manually when tracking an interaction.

npm install schedule

NOTE: The schedule API is unstable at the moment and could change slightly going forward.

Manual Tracking

Using the unstable_track function from schedule/tracking, we can manually add calls around code that will initiate a render or re-render. For our Redux TodoMVC app, let's update the TodoTextInput.js file and tweak the handleSubmit method. We'll take our onSave and setState code and provide it as a callback to the track function.


/* ... more code ... */
import { unstable_track as track } from 'schedule/tracking'

export default class TodoTextInput extends Component {
    /* ... more code ... */
    handleSubmit = (e) => {
        const text =
        if (e.which === 13) {
            track('Add Todo',, () => {
                if (this.props.newTodo) {
                    this.setState({ text: '' })
    /* ... more code ... */

At this point, if we re-record Profile data from our app we'll notice an entry in the Interactions tab. There is our "Add Todo" interaction! You can click on the entry for more details on the right panel, and you can also click to go straight to the associated render.

Automatic Tracking of Redux Actions

It could be quite cumbersome to manually add a bunch of track calls throughout your codebase. However, since this is a Redux app, let's create a function instead that iterates over the actions and wraps them in a track call automatically!


/* ... more code ... */
import { unstable_track as track } from 'schedule/tracking'

/* ... more code ... */

const trackActions = (object) =>
    Object.keys(object).reduce((memo, name) => {
        const action = object[name]
        memo[name] = (...args) =>
            track(name,, () => action(...args))
        return memo
    }, {})

const mapDispatchToProps = (dispatch) => ({
    actions: trackActions(bindActionCreators(TodoActions, dispatch)),

/* ... more code ... */

As before, we'll need to re-record to gather new Profiler data. Once the data is retrieved, we should see more interactions to investigate. In the following screenshot, you can see the original "Add Todo" track event and also two new track events that were a result of our Redux actions (completeAllTodos and clearCompleted).


The ability to profile a React application is very powerful and I’m super excited about having these advanced features in the React Developer Tools. Thank you React team!

Web Mentions

Tweet about this post and have it show up here!