DEV Community

Gaurav Suthar
Gaurav Suthar

Posted on • Updated on

When to use memo in React

Let's first understand how React re-renders

State change:
When a state change it re-render its component, it also re-render all of its descendants components.
Let's understand by an example

export default function App() {
  return (
    <div className="app">
      <Counter />
    </div>
  );
}

const Counter = () => {
  const [count, setCount] = useState(0);

  const handleCount = () => {
    setCount(count + 1);
  };

  return (
    <div className="counter">
      <Display count={count} />
      <button onClick={handleCount}>Count</button>
    </div>
  );
};

const Display = ({ count }) => {
  return <div>{count}</div>;
};

Enter fullscreen mode Exit fullscreen mode

So I'm not going to bore you to read every lines of the code. Here are highlights:

  • The main component is <App /> which renders <Counter /> and which renders <Display />, The Counter has count state and a button which triggers handleCount on click.

Whenever the count state change, the Counter component will re-render and it re-renders all of its descendents component.

But why App component didn't re-render?
The answer is very simple the count state is defined inside the Counter component and we are updating the count state, so it will re-render that component and its descendants.

After understanding how component re-renders in React, let's take a look at when to use memo() in React.

export default function App() {
  const [list] = useState(USERS); // List of users
  const [color, setColor] = useState("#fdd3c2");

  const handleColor = () => {
    const randomColor = getRandomColor();
    setColor(randomColor);
  };

  return (
    <div style={{ backgroundColor: color }} className="App">
      <List list={list} />
      <Button handleColor={handleColor} color={color} />
    </div>
  );
}

const Button = ({ color, handleColor }) => {
  return (
    <button className="button" onClick={handleColor}>
      {color}
    </button>
  );
};

const List = ({ list }) => {
  return (
    <ul>
      {list.map((item) => {
        return <li key={item.id}>{item.name}</li>;
      })}
    </ul>
  );
};

Enter fullscreen mode Exit fullscreen mode

Here are highlights:

  1. We have two state named list and color in App component. The App component renders two components List and Button
  2. The list state is passing to List component through prop and render the list inside List component.
  3. The color state is passing to Button component through prop.

so when the user clicks on button the color state is changed, because of color state defined inside App component. The Appcomponent re-render and it also re-render both List and Button component but here is the problem, why we want to re-render List component even though list state hasn't changed and also we are not passing color as a prop to right. It might be a performance problem if the list is too long.

We can wrap the whole List component inside memo() to avoid unneccesary re-render of component if the prop hasn't changed

...
const List = memo(({ list }) => {
  console.log("Re-render List")
  return (
    <ul>
      {list.map((item) => {
        return <li key={item.id}>{item.name}</li>;
      })}
    </ul>
  );
});
Enter fullscreen mode Exit fullscreen mode

Now, If we clicks on button to change the color, the <List> will not re-render because the list props has not changed and we wrapped the <List> component inside memo().

What does the mean of memo?
Memo means memoization (memorization), it is a cache technique in which react will re-use the previous snapshot if the none of props have changed rather than going to generating a brand new.

By this technique we can save unwanted re-renders of component if the props have not changed.

NOTE:

  • This is technique will not useful in most of scenerios, we must not have to wrap all of components inside memo()
  • This technique will not works on if the props are objects or function because objects or functions are recreate everytime on re-render. To use memo() techniques on objects and functions we can wrap objects and functions inside useMemo() and useCallback respectively

Codepen Link

Top comments (1)

Collapse
 
patidarmk profile image
patidarmk

I like your article, helpful info, keep up the good work 👍