React Performace Guide
Tags: react, performance, javascript
Published: 2021-09-09 10:16:23

As we know, React re-renders the component whenever there is change in state or props. There is no magical binding or any watcher which observes the state variable and updates it , infact it re-rendering of component which updates the UI. Each render has it's own props, state, event-listeners and effects, this is very well [explained](https://overreacted.io/a-complete-guide-to-useeffect/) by Dan.

### The Problem
In below code, Parent Component has 5 child components and all are rendered again even if the change is not related to them.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9as1k2fpjhjrw4j2pxg.png)
 
Here is how performance in impacted by unnecessary re-renders of components.
![re-renders](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvddcroyv7bq72btgqew.gif)

### The Solution
The first line of defense to avoid unnecessary re-renders is using **[React.memo](https://reactjs.org/docs/react-api.html#reactmemo)**. *React.memo* will skip rendering the component, and reuse the last rendered result.
Let's wrap all the child components in *React.memo*.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zw2pcubwx40949rahwx.png)

![react.memo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0f8qtn89d5e5w1tdx1z.gif)
We managed to save 3 components from re-rendering on change of Name input field, but still Address Input field re-renders. React.memo only does a shallow comparison of props changes but the *handleAddressChange* function is recreated new for each render and since functions are compared by reference, React.memo will not able to stop it from re-rendering Input Component as it is prop is callback function, which is new for each render of Parent Component.

The way to optimize this scenario is by using **[useCallback] (https://reactjs.org/docs/hooks-reference.html#usecallback)** hook.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chx5bmf4xhvnibgn1lcp.png)
Now we have re-rendering only for the components that require it, as callbacks are passed to **optimized** child components that rely on reference equality to prevent unnecessary renders

![React-useCallback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbc93m98cmrmuhohbna7.gif)

💡 Now  suppose if we have another requirement that is to validate address and show the suggestion. Address Validation API can take some time , lets see that in action 
```js
    const isValidAddress = () => {
    console.log(`validating Address... for ${city}`);
    for (let i = 0; i < 10000; i++) {
      //some delay to simualte address validation API
    }
    return city.length < 3 ? false : true;
  };
<!--  markup for address validation-->
 <Input
        target="Address"
        value={city}
        handleChange={memoizedAddressChange}
      />
      <span> Address is {isValidAddress() ? "✅" : "❌"}</span>
```

For this example , let's assume if address length is less than 3 then it's invalid  otherwise it's valid.

![React.useMemo (1)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c3ousrsy3xzvzlpfswn0.gif)
 
Now *isValidAddress()* which is an **expensive fn**, is getting called even if we are changing the name , it is happening due re-render of component due to change in name state. 
We can memoize the result of addressValidation function when we are changing any other state and only recalculate when there is change in address field.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9r26urwh1txbj2fhdmvs.png)

The optimized solution with **[useMemo](https://reactjs.org/docs/hooks-reference.html#usememo)** saves time of unnecessary evaluation of any expensive function.  ⤵
![useMemoSoln](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntwn6hme22ew59vbugbp.gif)

The difference between *useCallback()* and *useMemo()* is that useCallback is to  memoize/memorize the callback function that are passed to as props and useMemo is helpful in memozing the result of any expensive calculation.

---   

Here is full code example of above `concepts`:

{% codesandbox react-performance-ihsmn %}