Algobook
- The developer's handbook
mode-switch
back-button
Buy Me A Coffee
Wed Mar 22 2023

What is React memo, and how can we use it?

As the headline says, what is memo in React? Memo is an optimization technique that we can apply to our components to avoid unnecessary re-rendering.

The function provided by React will accept two arguments, where the second one is optional.

memo(Component, arePropsEqual?)

First argument is our component, and the second argument is a function for checking whether a components props has changed - and if it should re-render. The comparison for props are check by React per default with shallow equal, but if we need to override it, there is a possibility to do so. We will cover that in this guide further down.

Let's make an example

import { memo, useState } from "react"; const MemoizedComponent = memo() => { console.log("Render"); return <div>I don't rerender!</div>; }); const NotMemoizedComponent = ({ currentCount, children }) => ( <div> {currentCount} {children} </div> ); const Parent = () => { const [count, setCount] = useState(1); return ( <> <button onClick={() => setCount(count + 1)}>Add count!</button> <NotMemoizedComponent currentCount={count}> <MemoizedComponent /> </NotMemoizedComponent> </> ); };

In our above example, we now have three components. The Parent holds the count state which we change when the button is clicked. The component NotMemoizedComponent will re-render for each time the button is clicked. And we are also wrapping our memoized component inside the non-memoized component.

In the above example, the <MemoizedComponent /> component, will not re-render, since we are using the memo() function. If we remove memo(), we will see in the log that it will re-render everytime we click the button.

Memoized component with object as prop

Let's change our implementation a bit. We will now make the <MemoizedComponent /> accept an object.

const MemoizedComponent = memo(({ myObject }) => { console.log("RENDER"); return <div>{myObject.label}</div>; }); <> <button onClick={() => setCount(count + 1)}>Add count!</button> <NotMemoizedComponent currentCount={count}> <MemoizedComponent myObject={{ label: "I will never change" }} /> </NotMemoizedComponent> </>;

What happens now when we click the button? It re-renders!

So, what is going on? The problem here is that we are passing in an object. And in JavaScript, when we compare two objects, they are not equal.

Example:

const objectA = { firstName: "Peter" }; const objectB = { firstName: "Peter" }; objectA == objectB; // false

Solution

So to solve this, lets make use of the second argument of the memo() function.

Let's extend our <MemoizedComponent /> a bit

const arePropsEqual = (prevProps, newProps) => prevProps.myObject.label === newProps.myObject.label; const MemoizedComponent = memo(({ myObject }) => { console.log("RENDER"); return <div>{myObject.label}</div>; }, arePropsEqual);

All right, so now we are creating a function arePropsEqual and passing it in to the memo function as second argument.

And if we now click the button, everything is working fine and the component will only re-render if the prop has really changed.

Thanks for reading!

signatureWed Mar 22 2023
See all our articles