In this tutorial, you will learn 10 tips that will help you write more performant ReactJS components. Before we get into the implementation details, it would be good to define what I would consider a badly defined component. First, when you load a page, if your component starts to feel a little sluggish, or, the whole page starts to freeze, then it's likely that you've done something wrong. Adding one instance of your component to a page is OK, but what happens if you add two or more? If you have encountered these types of issues, and want to learn some new techniques to solve them, then read on.

A common mistake developers new to ReactJS tend to make when building components, is not paying enough attention to how many times that component gets re-rendered unnecessarily. When you build a React application built upon components, you implicitly build a hierarchical component tree. When a component passes some props to another component, it is called the Owner. An owner may have one or more children. When the owner component updates a prop, this update will cause a propagate of data down the component tree. This will then force all child components to re-render as well. If the owner is at the very top of the component hierarchy, this can cause a lot of updates. To make things worse, if you don't write your components with referential equality, in the majority of situations, these updates are completely unnecessary.

Out of the box, React helps alleviate this problem, with PureComponent. When you create a component that inherits from PureComponent for instance, React knows how to optimize the components state. It batches the operation for better performance. In earlier versions of React, if you created a stateless component, your component would be less performant. React did not provide state management on stateless components. This meant that stateless components got re-rendered over and over even when they hadn't changed. PureComponent has optimizations built-in. This is why it's a good practice to always try and extend from PureComponent.

If you have performance issues, then Chrome dev tools can be a lifesaver. If you look in the performance tab and record the performance of your page, you will be able to see a flame-graph of how your component behaves. You can use this flame graph to see if components are being re-rendered too many times. Another useful tip is to use the React developer extension for Chrome to make sure that there are no props that are unexpectedly changing and causing components to render unnecessarily.

Architecture

When building ReactJS components, a very common bit of advice is to follow the single responsibility pattern. Each component should only do one specific thing. One way to do this is to use something called a higher-order component. If you write components that try to do too many things, you'll end up with lots of props being passed into your component. Having too many props is undesirable, as it will make your code harder to understand, maintain, and change later on. Building high order components that compose functionality into child components, will keep your components small and minimize the number of props each component will require. The fewer props a component has the less likely it will be re-rendered unnecessarily. As a side benefit, it will also be easier to test!

Think About The Type of Props You Pass Into A Component

When passing props down into a component, you also want to consider the prop types that are being passed into it. Take the snippet below:

The code above has two main issues :

  • An object is used for a prop. Each time an object is passed into the component it is treated as a new object. As the object is new, referential equality will be broken within MyComponent, so the components render method will be re-run every-time

  • A function is being passed down as a prop. Whenever the parent component is updated this will cause MyComponent to rerender because the function would be treated as a new prop

Both objects and functions breaking referential prop equality. This is a cause of performance issues in your components.

Write Performant Components

To prevent breaking referential equality between components, there are a few techniques you can follow. First, instead of passing a new object each time, you should pass in individual properties and store them in state, like so:

Within MyComponents, you can add basic memorisation within shouldComponentUpdate(). This would remove the reliance on the external prop, making our code more efficient:

Another alternative (as of React v16.6 ) is to use functionless components and React Hooks or React context!!! Instead of relying on PureComponent and passing everything within a prop, you could use a hook and compose the data that your component needs instead. This will also prevent your component to re-render unnecessarily.

As well as ensuring referential equality between components, you should also think about:

  • Be very strict about not passing unneeded props into your components. The more props you pass in, the higher the chance your component will get re-rendered by a parent

  • Props cannot and should not be modified

  • Only store values in the state that are used within the render method

  • Nake use of children to make your components flexible

  • Immutable.js is a useful tool to ensure you do not accidentally mute your objects to prevent accidental renders

As you can see thinking about what props are passed into your components and how they are updated are key when creating a ReactJS application. The more optimal you can make your props the quicker your application will work. Happy Coding 🤘