React Memo, useMemo, useCallback - Optimize your performance
Tags: react, webdev, productivity
Published: 2022-06-17 13:37:37

Hello everyone!
In this blog we talk about how to optimize your react project.

In react there is a hook **React.memo** for optimizing the performance , and there is a **React.useMemo** also for optimizing the performance , another one is **React.useCallback** also for optimizing performance. so you are confused 😑 which one to used ?
let's dive in to the examples to understand you perfectly.
 
## Scenario where need to optimize
{% embed https://codesandbox.io/embed/goofy-gwen-6xjnhu?fontsize=14&hidenavigation=1&theme=dark %}

In the above example there is component named as **Child** 
and there is a counter state in **parent/app.js**. When you increment the counter the **Child component** also will be re-rendered (You can see the console after each click on the button)
while there is no state change in the child element ,then component will be re-rendered.

### What is the solution for stop un-usual re-rendering ?
There is a concept called **Memoization**. 
Let's see the definition of memoization

## What is memoization ?

> **Memoization** is an optimization technique that makes applications more efficient and hence faster🚀. It does this by storing computation results in cache, and retrieving that same information from the cache the next time it's needed instead of computing it again.

- A memoized function remembers the result of an output for a given set of inputs. It means when you give it set of inputs it remembers those inputs and also output associative with it. Whenever passing a set of input to the memoized function first it check in the **cached memory** whether the set of inputs is available or not, if they have its give you computed value from the cached memory.

- In React, we can memoized components (where the inputs are props) or functions.

Let's memoize our previous example:
We use **React Memo** for optimize this component example.

{% embed https://codesandbox.io/embed/fervent-oskar-gfur87?fontsize=14&hidenavigation=1&theme=dark %}

You can now check the console only first time render the child component after using React Memo.

## What is Callback ?

MDN definition  
> A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

Let's add an input field to the above example and pass props to child component function(setCounter) in which increase the counter value by calling this function.

{% embed https://codesandbox.io/embed/admiring-feather-simjzu?fontsize=14&hidenavigation=1&theme=dark %}

In above codeSandBox example if we type in the input field then child component get re-rendered(You can see console), while there is no props pass to the Child component which is related to state Input text field. Then why this happening ?🤔

The child component get re-render because when the parent component render in each time the inline function which is pass in the child component is **redefining the function calls another function which is called setCounter**.

```js
// passing function to the component
<Child updateCounter={() => setCounter((counter) => counter + 1)} />
```

Now, we want to pass callback function with memoize, so **React Memo** working properly. We use **useCallback** to memoize the callback functions. Let's code and look how can we use useCallback hook.

{% embed https://codesandbox.io/embed/crazy-torvalds-oh1xzy?fontsize=14&hidenavigation=1&theme=dark %}

```js
export default function App() {
// ...
const updateCounterFromChild = useCallback(() => setCounter(counter + 1), [
    counter
  ]);

return (
// Some Jsx returns
<Child updateCounter={updateCounterFromChild} />
 )
}
```
In useCallback({},[]) there is a dependency array list and we add dependency **counter** because the updateCounterFromChild function redefined only when the counter state is changed.

## What is useMemo ?

Definition by ⚛️reacts.org:
> **useMemo** will only recompute the memoized value when one of the dependencies has changed. This optimization helps to **avoid expensive calculations** on every render.
 
Let's understand with the above statement they said avoid expensive calculations on every render.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cw70thd4c08sr1ibglhj.gif)

{% embed https://codesandbox.io/embed/boring-minsky-3mofqj?fontsize=14&hidenavigation=1&theme=dark %}

In above example you can notice that there is very expensive calculation will be done as below you can see.

```js
(function () {
    console.log("Expensive calucation to be started...");
    let tempNumber = 0;
    for (let i = 0; i < 500_000_000; i++) {
      tempNumber++;
    }
  })();
```
In every click there is an delay for render the state of counter, because every click IIFE is called and doing expensive calculations. we don't want to re-rendered IIFE because every render we get same value from the previous render and this reason memoization comes.

We do two types of memoization in single example:
1. Don't calculate expensive calculation in each render.
2. I want to we update only **Second counter** in above example.

### useMemo vs useEffect

If you think we can do second part of the above statement with the help of **useEffect** then you can't do with this because, useEffect work for whole component of the app but useMemo can work for some part of the component. let's see with the code how useMemo work for some part of the HTML code.

{% embed https://codesandbox.io/embed/musing-williamson-q9vzt3?fontsize=14&hidenavigation=1&theme=dark %}

As you can see the above codeSandBox output the re-render after every click becomes smooth and there is no console of the IIFE.
First counter not get affected by the Increment click. If you want to update also the state of first counter then you pass dependencies array **counter** to the useMemo. 

Thanks for reading this blog with the patience 😊, and i suppose to be that you will get learn something from this blog.
Give your love💖 and feedback💬 to this blog.