03.28.2022 - React / Memoization with React.memo

Memoization is the technique to let an expensive function return the cached value if all of its arguments remain unchanged.

When a React component is wrapped inside a React.memo, the render result of that component will be memoized. If you pass the same props, React will skip re-rendering that component.

Let’s take a look at this example: We create a component Book that takes a string as title. And an “Update” button.

const BookComponent = ({ title }) => {
console.log("Render book with ", title);
return <div>{title}</div>;
};
const Book = BookComponent;

const DemoApp = () => {
const [title, setTitle] = React.useState("Hello, World!");
const update = () => {
setTitle("Hello, World!");
};
return (
<div>
<Book title={title} />
<button onClick={update}>Update</button>
</div>
);
};


Every time you click the “Update” button, we update the title state, the Book component will always be re-rendered, even if the title value remains the same.

To keep the Book component from being re-rendered, we can wrap it with React.memo:

const Book = React.memo(BookComponent);


Now, when updating the state, the BookComponent will be called, but the input props have been memoized before, so React will skip rendering.

By default, React.memo only do a shallow comparison on the props, this means, if the input prop is an object, the memoization will be broken.

For example, instead of taking a title string, we change the BookComponent to take an object instead:

const BookComponent = ({ book: { title } }) => {
console.log("Render book with ", book.title);
return <div>{book.title}</div>;
};
const Book = React.memo(BookComponent);

const DemoApp = () => {
const [data, setData] = React.useState({
book: {
title: "Hello, World!"
}
});
const update = () => {
setData({
book: {
title: "Hello, World!"
}
});
};
return (
<div>
<Book data={book} />
<button onClick={update}>Update</button>
</div>
);
};


Clicking “Update” will always result in a re-render. In this case, we can provide React.memo a custom comparison function:

const compare = (prevProps, currentProps) => {
return prevProps.book.title === currentProps.book.title;
};

const Book = React.memo(BookComponent, compare);


Now, memoization will work again.

It’s a best practice to only use React.memo on complex components or components that do not require an update when props change.