How to use the useMemo React hook

By

Learn how the useMemo React hook caches the result of an expensive calculation so it runs only once, and how the dependencies array controls recomputation.

~~~

Check out my React hooks introduction first, if you’re new to them.

useMemo caches the result of a calculation between renders. You give it a function and a dependencies array, and React only re-runs the function when one of the dependencies changes.

import React, { useMemo } from 'react'

This hook is used to create a memoized value.

This hook is very similar to useCallback, the difference is that useCallback returns a memoized callback and useMemo returns a memoized value, the result of that function call. The use case is different, too. useCallback is used for callbacks passed to child components.

Why do we need it?

A React component re-renders every time its state or props change. Everything in the component body runs again, including any calculation you do there.

Most calculations are cheap and nobody notices. But sorting or filtering a big list on every keystroke, for example, can make the UI feel slow.

useMemo lets you skip that work when the inputs didn’t change.

How to use it

Here’s how to use it, sorting a list of products by price:

const sortedProducts = useMemo(() => {
  return [...products].sort((a, b) => a.price - b.price)
}, [products])

The sort only runs when products changes. On every other render, React returns the cached array.

The second argument is the dependencies array. List every value from the component that the function uses. When one of them changes, the value is calculated again.

If the calculation depends on nothing, pass an empty array, and it runs only once:

const initialBoard = useMemo(() => buildChessBoard(), [])

Make sure you don’t omit the array entirely. Without it, React recomputes the value on every render, and no memoization happens at all.

A common pitfall

Be careful with values you use inside the function but forget to list in the array:

const total = useMemo(() => {
  return items.reduce((sum, item) => sum + item.price * taxRate, 0)
}, [items]) // taxRate is missing!

When taxRate changes, total stays stale, because React sees no reason to recompute. The fix is to add it to the dependencies: [items, taxRate].

Two more things to keep in mind. The function must be pure and synchronous: no network requests, no side effects. If you need to fetch data, that’s a job for useEffect.

And treat useMemo as a performance optimization, not a guarantee. React may discard the cached value in some cases, so your code must still work if the function runs again.

Tagged: React · All topics
~~~

Related posts about react: