Preventing unwanted re-rendering in Reactjs app with memo

1) When do unwanted re-renders happen?

For this article, I assume that you’re not new to React and already have a basic understanding of how React’s rendering mechanism works.

regarding the following code:

1import { FC, useEffect, useState } from "react";
2
3const Child: FC<{ counter: number }> = ({ counter }) => {
4  useEffect(() => {
5    console.log("Child re-render");
6  });
7  return <>Child counter: {counter}</>;
8};
9
10export const Parent: FC = () => {
11  const [counter, setCounter] = useState<number>(0);
12  const [counter2, setCounter2] = useState<number>(0);
13
14  return (
15    <>
16      <button onClick={() => setCounter((prev: number) => prev + 1)}>
17        Increase counter
18      </button>
19      <br />
20      <span>counter: {counter} </span>
21      <br />
22       <div>-----------------</div>
23      <br />
24      <button onClick={() => setCounter2((prev: number) => prev + 1)}>
25        Increase counter 2
26      </button>
27      
28      <br />
29      <Child counter={counter2}/>
30    </>
31  );
32};

let's run the code:

Clicking the “Increase counter” button will trigger the counter state to change, which in turn causes the Parent component to re-render. When the Parent re-renders, the Child component also re-renders, even though it doesn’t depend on the counter. (Line 5 will log each time this happens.)

This is an example of an unwanted re-render. It may not seem like a big deal when your app is small, but as it grows and becomes more complex, redundant re-renders like this can become a significant performance issue.

2) memo

React.memo is a higher-order component (HOC) that wraps a functional component and skips re-rendering it if its props haven’t changed (according to a shallow comparison).

import memo from react and wrap it around your component

1import { FC, memo, useEffect, useState } from "react";
2
3const Child: FC<{ counter: number }> = memo(({ counter }) => {
4  useEffect(() => {
5    console.log("Child re-render");
6  });
7  return <>Child counter: {counter}</>;
8});

run the code:

Now, when you click the “Increase counter” button, the Child component will no longer re-render despite the counter state change. It only re-renders when you update counter2, which is passed as a prop.