Advanced React Optimization Techniques
Tags: react, programming, javascript, productivity
Published: 2023-05-16 19:06:23

**_To read more articles like this, [visit my blog](https://www.mdfaisal.com/blog)_**


React is very fast. I mean really really fast. That’s what makes React great.

But if you want to optimize your application even more there are some ways you can do that.

Today we will look into the most useful two techniques provided by React itself to solve some performance issues.

### 1. Let’s Start Simple

Take a sample example where we have a component named `Display` that does nothing but show a single line of text.

This component is a child of `Controller` which has a button that increases a state variable named `count` and holds our `Display` Component.

```js
import React,{useState} from 'react';


const Controller = () => {

    const [count , setCount] = useState(0);

    return <>
        <button onClick={() => setCount(count => count+1)}> Click </button>
        <Display />
    </>
    
}

const Display = () => {

    console.log('display is re-rendering')

    return <div> This is a display function.</div>

}
```

Notice we have added a `console.log()` inside our `Display` component to find out if our component is re-rendering.

Now When we click on the button of the `Controller` component and open the console.

![](https://cdn-images-1.medium.com/max/2000/1*Nclw2ZLIyP1lBm9DLjH8sQ.png)

Although it has nothing to do with the component's view our component `Display` is a child of `Controller` its being re-rendered every time we press the button.

That’s not cool. What if we use this `Display` component all over our project?

The performance will take a hit.

### 2. What is Memoization You Ask?

Memoization is a very familiar technique used in many places. It's nothing but caching.

From Wikipedia the definition is
>  *In computing, **memoization** or **memoisation** is an optimization technique used primarily to speed up computer programs by storing the results of expensive [f](https://en.wikipedia.org/wiki/Subroutine)unction calls and returning the cached result when the same inputs occur again.*

So… If memoization is a technique to improve the performances of functions, can we do that for our functional components?

Yes, we can do that. In fact, React has provided us with a nice feature called `React.memo()`

Now we will see how we can use it to solve our current problem.

### 3. Using React.memo() to Prevent Re-render

`React.memo()` takes two arguments.

* The first one is the function that we want to memorize.

* The second one is an optional compare function just like `shouldComponentUpdate()` . We will call about that later.

So now if we pass our `Display` component into the `memo()` this should be memorized.

Let’s see what happens, If we rewrite our component like the following…

```js
import React,{useState , memo} from 'react';


const Display = memo(() => {

    console.log('display is re-rendering')

    return <div> This is a display function.</div>

})
```

And voila! Our component is now not re-rendering every time we click on the button.

### 4. Let’s Take This One Step Further

Okay so now you have an efficient component. But the problem is that component is absolutely dumb. You want to change the content of `Display` based on some props passed to it.

We will now re-write our component to show a list of names.

Also when we click on the button it adds a new name to our state.

```js
import React,{useState , memo} from 'react';

const Controller = () => {
    const [names , setNames] = useState([]);
    const addName = () => {
        const newNames = names;
        newNames.push('another name')
        setNames(newNames);
    }
    return <>
        <button onClick={() => addName()}> Add Name </button>
        <Display names={names}/>
    </>
}

const Display = memo((props) => {
    return <div>
        {props.names.map(name => <div>{name}</div>)}
    </div>
})
```

So we should see `another name` appended to the list of names whenever we click on the `Add Name` button.

But when we do that nothing happens. Why is that?

### 5. Mutable vs Immutable

To solve the problem we have to understand the concept of `Immutable` .

In the line `newNames = names` We are thinking that we are assigning `names` to a new variable `newNames` But in reality `arrays` in javascript doesn’t work that way!

In the background all this line is doing is assigning the reference of `names` array to the `newNames` . As a result, although the contents of the names array are changing the reference is not.

What React does here is a `shallow` checking. It only compares the previous reference of names array with the new reference. As it didn’t change react decides that there is no need to re-render.

We can solve this problem by re-writing our `addNewName` function like this…

```js
const addName = () => {
    const newNames = [...names];   // SEE HERE
    newNames.push('another name')
    setNames(newNames);
}
```

This spread operator returns a completely new array that is now assigned as `newNames` .

Now if we click on the button we will see that our component will re-render.

### 6. Where memo() Fails, useCallback() Comes to Rescue

Let’s take another example. We will create a component similar to our last component which will add a new name each time we click on the button.

And we will have another component that will clear that list.

```js
import React,{useState , memo} from 'react';


const Controller = () => {

    const [names , setNames] = useState([]);

    const addName = () => {
        const newNames = [...names];
        newNames.push('another name')
        setNames(newNames);
    }

    const clearNames = () => setNames([])

    return <>
        <button onClick={() => addName()}> Add Name </button>
        
        <div>{names.map(name => <div>{name}</div>)}</div>
        
        <ClearButton clearNames={clearNames}/>
    </>
}


const ClearButton = memo((props) => {

    return <div>
        <button onClick={props.clearNames}> Clear</button>
    </div>

})
```

Now, whenever we click on the `Add Name` button our `ClearButton` is re-rendering again and again unnecessarily!

That means although we memorized our `ClearButton` and the `clearNames` is not changing, our component is re-rendering unnecessarily.

To solve this problem we can use a hook named useCallback() . This useCallBack() hook helps us to avoid re-computing clearNames . It’s provided by React itself so we can import it like…

```js
import React,{ useCallback} from 'react';
```

We can rewrite the `clearNames` function as following to solve our problem.

```js
const clearNames = useCallback(() => setNames([]), [setNames])
```

And now our problem is gone!

So these are some ways you can use to improve the performance of your application. But every good thing comes with its own pitfalls. So try to use these techniques wisely to avoid any unwanted bugs.

That's it for today. Happy Coding!

**Get in touch with me via [LinkedIn](https://www.linkedin.com/in/56faisal/) or my [Personal Website](https://www.mdfaisal.com/).**