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)

Jetbrains Survey

Calling all developers!

Participate in the Developer Ecosystem Survey 2025 and get the chance to win a MacBook Pro, an iPhone 16, or other exciting prizes. Contribute to our research on the development landscape.

Take the survey