DEV Community

Cover image for Day 56 of #100DaysOfCode: Avoid useless re-rendering with React.memo for the customized hooks
Jen-Hsuan Hsieh
Jen-Hsuan Hsieh

Posted on • Edited on

Day 56 of #100DaysOfCode: Avoid useless re-rendering with React.memo for the customized hooks

1. Introduction

I create a React hook recently which is called 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 
Enter fullscreen mode Exit fullscreen mode
  • We can use the hook for endpoints that we want to monitor to
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 
Enter fullscreen mode Exit fullscreen mode
  • 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.
const Results = ({ results, status}) => { const refCount = React.useRef(0); refCount.current++; return ( <div> <p> {`render time: ${refCount.current}`} </p>  ... ) }; 
Enter fullscreen mode Exit fullscreen mode
  • We found that the child component was re-rendered whenever use-react-monitor return the value. However, what we expect is that the child component was re-rendered only when use-react-monitor return new values.

Alt Text

2. Avoid useless re-rendering with React.memo

React.memo 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 return new values.

Compare function

function monitoredPropsAreEqual(prevResults, nextResults){ return JSON.stringify(prevResults) === JSON.stringify(nextResults); } 
Enter fullscreen mode Exit fullscreen mode

Wrap the child component with React.memo

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); 
Enter fullscreen mode Exit fullscreen mode

Result

Alt Text

That's it!

Side projects

There are some of my articles. Feel free to check if you like!

References

Top comments (0)