Day 56 of #100DaysOfCode: Avoid useless re-rendering with React.memo for the customized hooks
Tags: react, 100daysofcode, javascript, hook
Published: 2021-01-28 11:19:00

## 1. Introduction

I create a React hook recently which is called [use-react-monitor](https://www.npmjs.com/package/use-react-monitor). It can help us to monitor endpoints for the specified interval and reset the interval when it changes.

* We have to install the package in the first step

```
npm install use-react-monitor -S
```

* We can use the hook for endpoints that we want to monitor to

```javascript
import React from 'react';
import useMonitor from 'use-react-monitor';

const Tester = () => {
    const interval = 3000;
    const {results, status, lastTimes} = useMonitor(
        { urls:['http://rem-rest-api.herokuapp.com/api/users',
                'http://rem-rest-api.herokuapp.com/api/users'],
          freshRate: interval});

    return (
        <>
            {<Results results = {results} status = {status}/>}
        </>
    )
}

const Results = ({ results, status}) => {
    const refCount = React.useRef(0);
    refCount.current++;
    return (
        <div>
        <p>
       {`render time: ${refCount.current}`}
        </p>
        {results && results.map((result, i) =>{
            return (
                <>
                    <div key={`status-${i}`}>Status: {status && status[i]}</div>
                    <ul key={i}>
                        {result.data.map((r, index) => {
                            return (<li key={index}>{r.id} {r.firstName} {r.lastName}</li>)
                        })}
                    </ul>
                </>)
        })}
     </div>
    );
};

export default Tester
``` 

* Then it can polling to fetch the resources from endpoints. 
Now we add *useRef* to check if the child was re-rendered even though the fetched result was unchanged. 

```javascript
const Results = ({ results, status}) => {
    const refCount = React.useRef(0);
    refCount.current++;
    return (
        <div>
        <p>
       {`render time: ${refCount.current}`}
        </p>
        ...
    )
};
```

* We found that the child component was re-rendered whenever [use-react-monitor](https://www.npmjs.com/package/use-react-monitor) return the value. However, what we expect is that the child component was re-rendered only when [use-react-monitor](https://www.npmjs.com/package/use-react-monitor) return new values.  
 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7akgnothlpy6zp3t2c7j.gif)

## 2. Avoid useless re-rendering with React.memo
[React.memo](https://zh-hant.reactjs.org/docs/react-api.html) is a HOC. We can pass our child component with the compare function and React.memo will perform shallow comparing.
The wrapped child component will only be re-rendered when [use-react-monitor](https://www.npmjs.com/package/use-react-monitor) return new values.  

### Compare function
```javascript
function monitoredPropsAreEqual(prevResults, nextResults){
    return JSON.stringify(prevResults) === JSON.stringify(nextResults);
}
```

### Wrap the child component with React.memo
```javascript
import React, {memo} from 'react';
const Tester = () => {
    const interval = 3000;
    const {results, status, lastTimes} = useMonitor(
        { urls:['http://rem-rest-api.herokuapp.com/api/users',
                'http://rem-rest-api.herokuapp.com/api/users'],
          freshRate: interval});

    return (
        <>
            {<MemorizedResults results = {results} status = {status}/>}
        </>
    )
}
const MemorizedResults = memo(Results, monitoredPropsAreEqual);
```

### Result

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nsdudn83ecmspveky104.gif)

That's it!

## Side projects
There are some of my articles. Feel free to check if you like! 
* [My blog-posts for software developing](https://medium.com/a-layman)
* [My web resume](https://jenhsuan.github.io/ALayman/cover.html)
* [Facebook page](https://www.facebook.com/imalayman)
* [Next.js website - Daily Learning](https://daily-learning.herokuapp.com/)
* [npm package - create-nrs-web](https://www.npmjs.com/package/create-nrs-web)
* [npm package - use-react-monitor](https://www.npmjs.com/package/use-react-monitor)
* [npm package - react-ui-gauge-component](https://www.npmjs.com/package/react-ui-gauge-component)

## References
* [How to create a customized React hook package and publish it to npm?](https://medium.com/a-layman/how-to-create-a-customized-react-hook-package-and-publish-it-to-npm-4fa966359c7b)
* [如何錯誤地使用 React hooks useCallback 來保存相同的 function instance](https://medium.com/@as790726/%E5%A6%82%E4%BD%95%E9%8C%AF%E8%AA%A4%E5%9C%B0%E4%BD%BF%E7%94%A8-react-hooks-usecallback-%E4%BE%86%E4%BF%9D%E5%AD%98%E7%9B%B8%E5%90%8C%E7%9A%84-function-instance-7744984bb0a6)
* [React.memo()](https://medium.com/@codingtownindia/react-memo-b83da437eebd)
* [一直以来`useCallback`的使用姿势都不对](https://segmentfault.com/a/1190000022988054)
* [Use React.memo() wisely](https://dmitripavlutin.com/use-react-memo-wisely/)
* [React Hooks 第一期：聊聊 useCallback
](https://zhuanlan.zhihu.com/p/56975681)