The performance of React relies on the architecture, components and libraries that you use in your application. To catch the performance chokepoint, you must first understand the underlying architecture.
If you’re reading this post, you’re probably familiar with React. I suppose that you are looking for reasons why your application does not work fast enough and how to speed up your React App.
This article covers 2 issues:
- Complex variables in render
- PureComponent/Recompose
What’s exactly wrong with React?
There’s nothing wrong with React itself. It’s more about the functional/reactive nature of this library that seems to be an issue.
React is a simple and light library just to… render the components which are compiled into HTML. Communication between modules or classes is usually done via props from a parent. Each time the props are changed, the render method of all components is triggered. It’s called one-way data binding or unidirectional flow. Sounds great?
In small and simple apps this approach works very well. But sometimes, when our project is growing to include new features, we can see that performance drops. Loading views takes more time, refreshing components seems to be harder than before. You may ask yourself:
Why? What did I do wrong?
The answer is: render.
Render is the most memory-consuming function. But when we plan our app structure in a good way, we can prevent unnecessary rendering. Before we start, however, let’s define what “long loading time” means exactly. Fortunately, why-did-you-update comes with help. This library will let us know how often components render in a particular view.
Complex variables in render
Perhaps most of us have heard of react lifecycle method, shouldComponentUpdate. This method gives us control over when the component should update. Shocking ;)? But in this article I will tell you one thing:
Before you use this function, check your render method.
Solution: Avoid complex data declaration in render.
Let’s consider a simple example. We have two components: Box and Paragraph. Box contains Paragraph and listens to prop ‘clicks’. Paragraph has an options prop, with text and style. Each time ‘clicks’ is changed, Box is rendered. What about Paragraph? It shouldn’t be refreshed.
Even if we block Paragraph from an unnecessary update, it’s still refreshed when the parent gets new props. Indeed, our Paragraph gets a new prop as well because an options object is created each time Box render is triggered. Going deeper, in Paragraph shouldComponentUpdate method we always get a new object in nextProps parameter. In JavaScript, objects comparison relies on references. So even if we have an object with the same shape, the object from nextProps points to a new prop. In this case, the solution will keep our options object as variable or property of class:
This example is based on an object, but the same happens with arrays and functions.
As you can see, all the components are written as classes. Personally, I prefer to use stateless components because they are more readable, and help us avoid this context problem. In this case Recompose library comes with help.
PureComponent/Recompose
To prevent re-rendering (sorry, our jargon) Paragraph in our example, we had to write it as a class and define ‘shouldComponentUpdate’ method. This can be done more easily thanks to Recompose which gives us a lot of helpful hoc’s.
Solution: I recommend using pure higher-order component or PureComponent class from React.
Let’s see how this example can be written in that way:
And using PureComponent:
If you want to familiarize yourself with other methods of this library, and there are a lot of them, visit -> recompose.
I hope the tools and techniques presented in this blog post will help you make react apps faster.
Thanks for reading. If you want to learn about Reselect and Redux good practices,
take a look at my new post coming soon. So, stay tuned.