Skip to main content
Post image
· 6 min read

React useMemo hook guide with examples

Introduction​

This post is about how to use the useMemo() hook in React.

useMemo() is a function that returns a memoized value of a passed in resource-intensive function. It is very useful in optimizing the performance of a React component by eliminating repeating heavy computations.

In this post, we dive into the details of the useMemo hook with an extension of the example demonstrated in the previous post titled Memoization using React memo.

Steps we'll cover:

Project Content Overview​

The example app is based on the idea of a list of posts on a blog. There are several components involving a user seeing the latest posts and a list of the user's posts. Allow yourself some time to understand the components individually, their relationships, their state changes, and how props are passed through. It is crucial to pay close attention to how the change of a parent's state triggers the re-render of its descendants.

Here you can find the example app's live code

The discussion of this article is focused on optimizing performance by memoizing the value of resource-intensive functions, such as a sorting function. In React, we do this with the useMemo() hook.

Resource Intensive Functions​

We're going to jump back to the <Blog /> component for this example:

src/components/Blog.jsx
import React, { useEffect, useState } from 'react';
import fetchUpdatedPosts from '../fetch/fetchUpdatedPosts';
import allPosts from './../data/allPosts.json';
import sortPosts from '../utils/sortPosts';
import LatestPost from './LatestPost';
import UserPostsIndex from './UserPostsIndex';

const Blog = ({ signedIn }) => {
const [updatedPosts, setUpdatedPosts] = useState(allPosts);
const [localTime, setLocalTime] = useState(new Date().toLocaleTimeString());

const getLatestPosts = () => {
const posts = fetchUpdatedPosts();
setUpdatedPosts(posts);
};

const sortedPosts = sortPosts(updatedPosts);

useEffect(
() => {
const id = setInterval(
() => setLocalTime(new Date().toLocaleTimeString()),
1000
);
return () => clearInterval(id);
},
[]
);

console.log('Rendering Blog component');

return (
<div className="container">
<h1>Memoization in React</h1>
<div>
<div>
{ /* More JSX code here... */ }
<LatestPost signedIn={signedIn} post={sortedPosts[0]} />
</div>
<UserPostsIndex signedIn={signedIn}/>
</div>
</div>
);
};

export default React.memo(Blog);

We'd like to focus particularly on the sortPosts() utility function which can get expensive if passed a long array of posts.

At the moment, we are only sorting 101 items returned from fetchUpdatedPosts(), but in an actual application, the number can be much higher and consume resources at scale. Thus it is an expensive function.

If we look inside the useEffect() hook, we are updating the locale time string and storing it in localTime for our clock. localTime updates every second, and at each state, change triggers a re-render of <Blog />. The clock does not represent a genuine UI feature for us here, but it is there to make a point about how frequent re-renders complicate things with expensive utility functions.

Our sortPosts() logs Sorting posts... to the console and returns a sorted array from the passed in an array:

src/utils/sortPosts
const sortPosts = posts => {
console.log('Sorting posts...');
return posts.sort((a, b) => b.id - a.id);
};

export default sortPosts;

If we look at the console, we see that Sorting posts... is being looged at 1000ms intervals, i.e. with the tick of our clock:

usememo1

This shows sortPosts() is called at every re-render of <Blog />. An expensive function, invoked every second for no obvious reason, is too much of an ask from the app. We don't want sortPosts() to be called if updatedPosts is not changed.

Enter useMemo()​

useMemo() helps us memoize the value of sortPosts() when updatedPosts doesn't change. Let's use the memoized function:

src/components/Blog.jsx
-- const sortedPosts = sortPosts(updatedPosts);
++ const sortedPosts = useMemo(() => sortPosts(updatedPosts), [updatedPosts]);

Checking our console, we can see that Sorting posts... has been logged only once, indicating only one invocation of sortPosts():

usememo2

This gives us a huge performance gain.


github support banner

useMemo Dependencies​

Notice the dependency of useMemo() as the second argument, updatedPosts. We are asking the hook to renew the memo when updatedPosts changes. Let's try to change the value of updatedPosts:

In the <Blog/> component, we have a Get Latest Post button, which is used to fetch latest posts on demand. Every time Get Latest Post button is clicked, updatedPosts is updated with the invocation of getLatestPosts().

If the state of updatedPosts is changed, a re-render of <Blog /> is triggered, which leads to a call to sortPosts() with the new value of updatedPosts passed in.

If we check our console while clicking the button, we can clearly see Sorting posts... being logged for each click:


usememo3

info

It is important to notice that, if we remove the dependency from useMemo(), sortPosts() will not be invoked when updatedPosts change:

  const sortedPosts = useMemo(() => sortPosts(updatedPosts), []);

There is no sorting going on when we need it:

usememo4


It is also important to know that useMemo returns a value, as opposed to a function. This is what differentiates it from the useCallback() hook, which returns a memoized function. So, useMemo() is preferred for memoizing a value rather than a callback function.

Conclusion​

In this article, we looked into the use of useMemo() hook and found out it plays a crucial role in optimizing the performance of our app by memoizing an expensive utility function. We saw that it is important to specify the dependency of useMemo so that the memo is renewed when the state of dependency changes.

In the next post, we will demonstrate the use of useCallback() hook.


discord banner

Live StackBlitz Example​


Build your React-based CRUD applications without constraints​

Low-code React frameworks are great for gaining development speed but they often fall short of flexibility if you need extensive styling and customization for your project.

Check out refine,if you are interested in a headless framework you can use with any custom design or UI-Kit for 100% control over styling.

refine blog logo

refine is an open-source React-based framework for building CRUD applications without constraints. It can speed up your development time up to 3X without compromising freedom on styling, customization and project workflow.

refine is headless by design and it connects 30+ backend services out-of-the-box including custom REST and GraphQL API’s.

Visit refine GitHub repository for more information, demos, tutorials, and example projects.



Related Articles

Web Developer
A Quick Start Guide to React Suspense
· 5 min read
Software Engineer
When to use dangerouslySetInnerHTML in React?
· 6 min read
Frontend Developer
How to Multipart File Upload Using FormData with React Hook Form
· 7 min read

From Same Author

Fullstack Developer
Memoization in React - How useCallback Works
· 7 min read
Fullstack Developer
React memo guide with examples
· 11 min read
Fullstack Developer
Javascript Currying - Variadic Currying
· 9 min read