Deeper Dive Into React useMemo
Tags: react
Published: 2021-09-25 15:51:23

---
title: Deeper Dive Into React useMemo
published: true
date: 2021-09-25 00:00:00 UTC
tags: react
description: When to use and not use React's useMemo
canonical_url: https://bionicjulia.com/blog/deeper-dive-into-react-usememo
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fpiqhe602bblxl8x2sa.jpg
---

If you're new here, be sure to first check out my posts on the [differences between React.memo and useMemo](https://bionicjulia.com/blog/react-memo-and-usememo-whats-the-difference), and a [deeper dive into React.memo](https://bionicjulia.com/blog/deeper-dive-into-react-memo). This post completes the last in the series and talks about the `useMemo` hook and when / when not to use it.

### When to use `useMemo`

**Use Case 1: Stopping computationally expensive, unnecessary re-renders**

Let's go back to the example I had in my [first post](https://bionicjulia.com/blog/react-memo-and-usememo-whats-the-difference). This illustrates the use case where you have a function that keeps re-rendering, because the state of its parent component keeps changing.

```jsx
export type VideoGameSearchProps = {
  allGames: VideoGameProps[],
}

export const VideoGameSearch: React.FC<VideoGameSearchProps> = ({ allGames }) => {
  const [searchTerm, setSearchTerm] = React.useState('')
  const [count, setCount] = React.useState < number > 1

  // NOTE useMemo here!!
  const results = useMemo(() => {
    console.log('Filtering games')
    return allGames.filter((game) => game.name.includes(searchTerm))
  }, [searchTerm, allGames])

  const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
    setSearchTerm(event.target.value)
  }

  const onClickHandler = () => {
    setCount((prevCount) => prevCount + 1)
  }

  return (
    <>
      <input type="text" value={searchTerm} onChange={onChangeHandler} />
      {results.map((game) => (
        <VideoGame key={game.name} rating={game.rating} name={game.name} releaseDate={game.releaseDate} />
      ))}
      <br />
      <br />
      <p>Count: {count}</p>
      <button onClick={onClickHandler}>Increment count</button>
    </>
  )
}
```

This is a completely made-up example which would likely never exist in production code, but I wanted to illustrate the takeaway points clearly. In this case, there are 2 things going on in this component:

- A user can click on an "increment count" button which updates the `count` state and displays the current number in the UI.
- A user can enter a search query in the input field which updates the `searchTerm` state `onChange`. This in turn causes the `results` function to re-calculate, where `results` is rendered as a list in the UI.

The incrementing of `count` has nothing to do with how `searchTerm` is set, or `results` run. However, every time `count` is incremented, the component re-renders and runs the `results` function. It's probably not going to be a big deal here, but what if the `allGames` array actually contains millions of elements... and instead of a simple filter function, it was a much more computationally complex calculation? This is where `useMemo` would come in handy.

Wrapping the `results` function with `useMemo` (with `searchTerm` and `allGames` as dependencies) tells React to only re-run this function, if either of those 2 variables changes. This means that changes in `count` would no longer cause `results` to be recalculated, with the memoised result being returned instead.

_Note: I've added the `console.log` in there so you can test it for yourselves to see how many times that function runs with and without the `useMemo` when you increment `count`!_

**Use Case 2: Ensuring referential equality when dealing with dependency lists**

If you have a case whereby you're relying on a dependency list, e.g. when using a `useEffect` hook, you really want to ensure you're only updating the component when the dependency values have truly changed.

```jsx
useEffect(() => {
  const gameData = { name, publisher, genres }
  thisIsAFunction(gameData)
}, [name, publisher, genres])
```

In this example, assuming `name`, `publisher` and `genres` are all strings, you shouldn't have a problem. React does a referential equality check on `gameData` to decide whether the component should be updated, and because `gameData` only comprises strings (i.e. primitives), this will work as we expect.

To illustrate the point, we wouldn't want to have this for example, because `gameData` will be a new instance every time React runs the `useEffect` check, which means re-running `thisIsAFunction` every time because in Javascript-land, `gameData` has changed.

```jsx
const gameData = { name, publisher, genres }

useEffect(() => {
  thisIsAFunction(gameData)
}, [name, publisher, genres])
```

So back to this - all good right?

```jsx
useEffect(() => {
  const gameData = { name, publisher, genres }
  thisIsAFunction(gameData)
}, [name, publisher, genres])
```

Unfortunately not, because we run into a similar problem if one of `name`, `publisher` or `genres` is a non-primitive. Let's say instead of a string, `genres` is actually an array of strings. In Javascript, arrays are non-primitives which means `[] === []` results in `false`.

So to expand out the example, we've got something like this:

```jsx
const GamesComponent = ({ name, publisher, genres }) => {
  const thisIsAFunction = (
    gameData, // ...
  ) =>
    useEffect(() => {
      const gameData = { name, publisher, genres }
      thisIsAFunction(gameData)
    }, [name, publisher, genres])

  return //...
}

const ParentGamesComponent = () => {
  const name = 'God of War'
  const publisher = 'Sony'
  const genres = ['action-adventure', 'platform']

  return <GamesComponent name={name} publisher={publisher} genres={genres} />
}
```

In this case, despite `genres` in effect being a constant array of strings, Javascript treats this as a new instance every time it's passed in as a prop when `GamesComponent` is re-rendered. `useEffect` will thus treat the referential equality check as false and update the component, which is not what we want. 😢

This is where `useMemo` comes in handy. The empty `[]` effectively tells React not to update `genres` after mounting.

```jsx
const ParentGamesComponent = () => {
  const name = 'God of War'
  const publisher = 'Sony'
  const genres = useMemo(() => ['action-adventure', 'platform'], [])

  return <GamesComponent name={name} publisher={publisher} genres={genres} />
}
```

_Side note: if one of the props is a callback function (i.e. not a primitive), use the `useCallback` hook to achieve the same effect._

### When not to use `useMemo`

Alright, so if not already clear by now after 3 posts, let me reiterate that React is smart and speedy in its own right. So, unless you're experiencing "use case 2" above, or perhaps "use case 1" with a noticeable lag or quantifiable performance dip, err on the side of **not** using `useMemo`! 😜