Faster React: Pure Components

An exercise with the React developer tools

It is easy to start blazing trails in a React app without taking the necessary steps to avoid future performance issues. You get into a flow state and the components are just blasting out of your keyboard. Before you know it, you have got a 100 components all with event handlers, state, props, context and asynchronous calls to apis everywhere.

Everything is working great, things are snappy and smooth like butter. You release the app into the wild, it is a hit! 10,000 users nearly over night. ūüí•

Then things start to slow down. You start getting complaints about initial app load times and general sluggishness throughout your app. ūüė≠

This kind of scenario is one we all hope to simply completely avoid, however things happen. In this post we will explore how to identify components that are slow and what to do about it.

3 Steps to Success

1.  Identify components that are causing performance issues using React Profiler (see section below on how to install)

2.  Investigate components to determine why they are slow.

3.  Make small changes, test for improvement, rinse and repeat.

Identifying Performance Issues

The React Profiler is a great tool for investigating how many times your components are being rendered and how long it takes. To use the React Profiler you go to the "Profiler" tab, click the little dot to start recording and then you click it again to stop recording. You are then presented with the rendering activity in an interactive diagram.

One of the best ways to learn is by doing, so I have created an experiment for you to help understand how to identify performance issues using the React Profiler.

In this experiment you will need to install the React developer tools and then investigate 2 different React apps. Each app has the same code with the exception that one has been slightly optimized using a technique we will cover shortly.

1. Install React Developer Tools

To begin if you have not already added the React Developer Tools, here are links to do so:

2. Investigate the Non-Optimized React App‚Äć

  • Go to https://react-performance-tuning.netlify.app/
  • Open up your dev tools and go to the "Profiler" tab that was added after you installed the React Developer tools
  • Click the little dot in the top left to begin recording
  • Wait 10 seconds
  • Click the little dot in the top left to stop recording
  • You should now see something that looks like this:
What are your observations?


3. Investigate the Optimized React App

  • Go to https://react-performance-tuning-optimized.netlify.app/‚Äć
  • Open up your dev tools and go to the "Profiler" tab that was added after you installed the React Developer tools
  • Click the little dot in the top left to begin recording
  • Wait 10 seconds
  • Click the little dot in the top left to stop recording
  • You should now see something that looks like this:
What are your observations now?

‚Äć

Results

Did you notice the difference?

You should have seen that in the optimized React app many of those green blocks are now grey, which means they did not re-render.

How is this possible?

The way this was achieved was by using a pure component, i.e. a component that only renders if its props change. You can create pure components either by using a class component that inherits from PureComponent or by using the memo function to wrap a function component.

Let's talk a bit more about pure components.

Pure Components

As we discussed above pure components only re-render when their props change. Let's look at a class example vs a function example, each works essentially the same.

Class Example

‚Äć

```language-javascript
export class Block extends PureComponent {
 render() {
   const { isActive, value } = this.props;
   return (
     <div className={[styles.container, isActive ? styles.active : null].filter(Boolean).join(" ")}>
       {value}
     </div>
   );
 }
}
```

Function Example

‚Äć

```language-javascript
export const Block = React.memo(({ isActive, value }) => {
 return (
   <div
     className={[styles.container, isActive ? styles.active : null]
       .filter(Boolean)
       .join(" ")}
   >
     {value}
   </div>
 );
});
```

Summary

Hopefully this exercise shined some light on how you can begin to approach performance issues with your React apps. This was achieved by using the React developer tools to profile our app to determine what components are rendering that do not have to. We then looked at how by using pure components we can prevent unnecessary re-renders.

In the next post we will look at other things to look into to determine what your bottlenecks are and how to address them.