5 quick and easy fixes to improve your React app performance 🚀 
Tags: react, webdev, performance, profiler
Published: 2020-01-14 11:34:58

---
title: 5 quick and easy fixes to improve your React app performance 🚀 
published: true
description: A guide on how to fix your React app performance with 5 easy tricks
cover_image: https://i.imgur.com/srvkx6w.png
tags: react, web development, performance, reactjs, profiler
---

**If** you've ever made a web application with React and are worried about how it will perform on different platforms/browsers/networks etc, then you need to look at its performance. It's most likely that while doing that [`create-react-app`](https://create-react-app.dev/) command, the ever-growing JavaScript library to build user interfaces has already done a few optimisations when you ran that command. So, why do we need to check performance again? 

Well, to be fair that command has done 50% of your work already. Now think your application is out on production, you made an e-book store which is used by thousands, they're making their accounts, purchases, adding items to cart, reviewing items and more. With so much heavy-lifting, it makes sense to actually enhance our web app by testing it under different conditions like simulating it on a lower-end mobile device with slow network speed. After all user experience matters the most!

Let's see how you can improve a slow or not-so-responsive React app in the following 5 fixes:


#### 1️⃣ Code Splitting

Of course, this comes built-in with [Webpack](https://webpack.js.org/), so naturally React has it too. Let's take that e-book app example. When you first visit the website you've downloaded all the JavaScript code used to run it. Even if it has 4-5 pages in navigation, your browser got each and every byte of data for the entire app. What if we limit this to this that when a user needs a specific page, only that code is loaded/fetched which is necessary.

> Code splitting is the way which allows you to split your code into various _bundles_ which can then be loaded on-demand.

This approach is used so that we get smaller bundles of data along with prioritizing which component to load where. All of this, if implemented correctly will have a major impact on your entire application.

We can use `React.lazy` 😴 along with `Suspense` 🚟 to make it happen. React `lazy` is a component that allows us to render a component's `import` dynamically in the form of a regular component.

##### Here's how we do it 💪

Suppose we have a `HomePage` component which we want to render lazily, we pass it as: 

```javascript
const LazyHomePage = lazy(() => import('.pages/homepage/homepage.component'));
```

The `lazy` takes a function that calls a dynamic `import()` inside which we pass in the path to our component. Next, we need to remove the actual import statement we're making up until this point. Now comes `Suspense`. This is used to defer rendering part of your application tree until some condition is met. The LazyHomePage component you made above can now be used inside the new `<Suspense />` block as:

```javascript
...
<div>
    <Suspense fallback={<CustomLoader />}>
        <LazyHomePage />
    </Suspense>
</div>
...
```

The `fallback` property you see above can point to any HTML element or some other component. The best use case I see of this is to make some sort of loading indicator page so that when the user navigates from one page to another within the application, this `CustomLoader` is shown as a `fallback`.

![404 error](https://media.giphy.com/media/OiC5BKaPVLl60/giphy.gif)
<figcaption>Just so that your users don't do this ヾ(≧ ▽ ≦)ゝ</figcaption>

To learn more about `Suspense`, check out Eyal Eizenberg's article:

{% medium https://itnext.io/trim-the-fat-from-your-bundles-using-webpack-analyzer-react-lazy-suspense-70dfa0ea93d2 %}


#### 2️⃣ Error boundaries 

What if while fetching the data from a backend server, your users aren't able to process the payments of the book because there seems to be a network issue? In fact, if an error comes back we really need something to handle it because the `Suspense` thing you did earlier will not know what to do in that situation.

Error boundaries to the rescue! 🦸‍♂️ It's simply a way for us to write a unique component that will catch an error and renders some _fallback_ interface instead of just that error coming the way of a customer visiting your online store. 

> Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. 

We can easily convert a class component to an error boundary if it defines the [`getDerivedStateFromError()`](https://reactjs.org/docs/react-component.html#static-getderivedstatefromerror) or [`componentDidCatch()`](https://reactjs.org/docs/react-component.html#componentdidcatch) lifecyle methods. In short the `getDerivedStateFromError()` is used to render a fallback UI after an error has been thrown and `componentDidCatch()` is used simply to log out the error information to the console.

##### Here's how we do it 💪

Inside of our component's local state let's have a boolean property called `hasError` which lets us know whether the state has an error in it or not. Initially, it's false. Inside our `getDerivedStateFromError()` method we do this:


```javascript
static getDerivedStateFromError(error) {
    // Process the error here
    return { hasError: true };
  }
```

It takes the `error` parameter be as default and we return the object representing the new state which we want to set locally. For componentDidCatch() we can simply use `console.log(error);` Now we conditionally want to return a different UI depending upon whether or not the local state's `hasError` property is `true` or `false`. This is how we do:

```javascript
render() {
    if(this.state.hasError) {
        return <ErrorComponent />
    }
    return this.props.children;
}
```

We can return an `ErrorComponent` which may contain a layout similar to this...

![404 error GIF](https://media.giphy.com/media/xTiN0L7EW5trfOvEk0/giphy.gif)

Then finally, we can wrap the `Suspense` inside of this new `ErrorBoundary` component we wrote above. 


#### 3️⃣ Component level optimizations

This can be classified into:

1. `shouldComponentUpdate`
2. `React.memo`
3. `React.PureComponent`

The `shouldComponentUpdate` is a lifecycle method which we have access to in a class component. It receives two `nextProps` and `nextState`. This comes in handy when we want to save our application from unnecessary re-rendering. Here's a small example:

```javascript
shouldComponentUpdate(nextProos, nextState) {
    console.log('method called', nextProps);
    return nextProps.text !== this.props.text;
}
```

This method is invoked before rendering when new props or state are being received. 

`React.memo` is similar to the `PureComponent` which we will discuss later. The main difference is that it's used for functional components while the later is used for class-based components. In a simple sentence:

> It allows the component to check the old props against new ones to see if the value has changed or not.

##### Here's how we do it 💪

`React.memo` is a [Higher-Order Component (HOC)](https://reactjs.org/docs/higher-order-components.html) so just like other HOCs you can start [memoizing](https://medium.com/@planttheidea/memoize-react-components-33377d7ebb6c) by passing your component inside `React.memo()` like so:

```javascript
export default React.memo(BooklistComponent)
```
Finally, `React.PureComponent` comes with `shouldComponentUpdate()` lifecycle method and implements it with a shallow prop and state comparison. **You should use  `React.PureComponent` instead of the usual `React.Component` when the `render()` function outputs the same result given the same props and state.** This certainly gives a performance boost to your React application.


#### 4️⃣ Using React Hooks

The two major hooks to solve performance issues are:

1. `useCallback()`
2. `useMemo()`

> The `useCallback` hook allows us to memoize a function that we wrap in it and use that same function if it already exists. 

Syntactically, it has two arguments; first is the function we want to memoize, the second is an array of dependencies and it's mandatory for it to work. If your function doesn't depend on anything, you can simply pass an empty array like so:

```javascript
const loggerFunction = useCallback(() => console.log('This logs via useCallback'), []);
```
As it's memoized, this callback will only change if one of it's dependencies were changed. This definitely helps to optimise child components that rely on others to prevent re-rendering of components, thus improving load times! 

> The `useMemo` hook is especially useful when you want to avoid expensive calculations on render. It only recomputes the memoized value when one of the dependencies has changed.

##### Here's how we do it 💪

Let' say we have a function which has to do some complex calculations, here how it's before the `useMemo` hook:

```javascript
const aComplexFunction = () => {
    console.log("I'm computing a complex problem!");
    return ((firstNum * 1000) % 15.6) * 8340 - 5489;
}
```
This is after the hook:

```javascript
const aComplexFunction = useMemo(() => {
    console.log("I'm computing a complex problem!");
    return ((firstNum * 1000) % 15.6) * 8340 - 5489;
}, [FirstNum]);
```
Just like the `useCallback`, this one also takes an array of dependencies. If no array value is provided, a new value will be computed on every render.


#### 5️⃣ Using React Profiler

> It's a component that allows us to check how much time (or cost) it takes for our component to render or mount. 

If you've played with the [React Dev Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) extension's Profiler tab, it's similar to that. 

##### Here's how we do it 💪

We just wrap it around whichever component we want to measure the cost. It takes two properties; the first is an `id` (String) which's an identifier to distinguish which Profiler is logging which component as Profiler can be used in multiple components, the second is a callback function called `onRender` which can take multiple arguments. Most common ones of those are `id` (String identifier we passed in), `phase` (either "mount" or "update") and `actualDuration`(time in milliseconds to render the component).

```javascript
<Profiler id="Homepage" onRender={(id, phase, actualDuration) => {
  console.log({id, phase, actualDuration});
  }}>
  <HomePage />
</Profiler>
```

### Read more! 

- https://reactjs.org/docs/optimizing-performance.html
- https://medium.com/myheritage-engineering/how-to-greatly-improve-your-react-app-performance-e70f7cbbb5f6
- https://www.codementor.io/blog/react-optimization-5wiwjnf9hj

---

_And there you go! I hope I've explained these five fixes in the right way. This is my first article on React so if you find any mistakes or suggestions feel free to write them in the comments! 😁_

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="en" dir="ltr">Don&#39;t think comments count... 🤭<br><br>Source: <a href="https://t.co/A8UgpqYkLi">https://t.co/A8UgpqYkLi</a><a href="https://twitter.com/hashtag/DevHumour?src=hash&amp;ref_src=twsrc%5Etfw">#DevHumour</a> <a href="https://twitter.com/hashtag/IDE?src=hash&amp;ref_src=twsrc%5Etfw">#IDE</a> <a href="https://twitter.com/hashtag/Programmer?src=hash&amp;ref_src=twsrc%5Etfw">#Programmer</a> <a href="https://t.co/LSJCtRBFyY">pic.twitter.com/LSJCtRBFyY</a></p>&mdash; Microsoft Developer UK (@msdevUK) <a href="https://twitter.com/msdevUK/status/1216769383789481989?ref_src=twsrc%5Etfw">January 13, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


---

#### [📫 Subscribe to my weekly developer newsletter 📫](https://mailchi.mp/f59beeac6b9b/devupdates)

##### PS: From this year, I've decided to write here on DEV Community. Previously, I wrote on Medium. If anyone wants to take a look at my articles, [here](https://medium.com/@vaibhavkhulbe)'s my Medium profile.