Understanding useMemo Hook in React [Complete Guide]

Dillion Megida
June 7, 2022
Try Memberstack for Free

TABLE OF CONTENTS
GET STARTED
Try Memberstack

The useMemo hook is used for memoizing values in React Applications. useMemo memoizes computed values in a React component so that in cases of a component re-render, those values will not be recomputed. This article will teach you what a useMemo hook is and how to use it.

What is a useMemo hook and what is it used for?

React has so many in-built hooks that allow you to do different lifecycle stuff in functional components, and there’s the useMemo hook. Why would you need this hook?

This hook is used for memoizing values in React applications. Memoization is an optimization technique that involves storing computed values in memory to avoid recomputation. This process speeds up program execution as computations would only have to execute once until specified to recompute.

Bringing this understanding to React, the useMemo hook memoizes computed values in a React component such that in cases of a component re-render, those values will not be recomputed.

The syntax of this hook is:


...
const value = useMemo(() => {
  return somevalue
}, [...dependencies])
...


It receives two arguments: a callback function that returns a value assigned to the variable and a dependencies array. The dependencies array informs the useMemo hook of when it needs to recompute a value, i.e., when one of the dependencies’ value changes, a recomputation happens, but until then, no recomputation.

Use cases of the useMemo hook

Avoiding Expensive Recomputation during Rerender

When a state is updated, the component is rerendered, and every value that may have been computed when the component mounted will be recomputed with the new state. For simple calculated values, this may not be a big deal. But for expensive calculations (like slow functions or functions that are doing so many things in them), optimization would be recommended.

Some computed values in React components depend on the state being updated, so when the state changes, we expect a recomputation of that value to get updated data. However, some computed values may depend on a different state, and this means such values should not be recomputed all the time.

And this is where useMemo comes in. Let’s look at an example without useMemo:


function App() {
  const [number, setNumber] = useState(0)
  const [darkTheme, setDarkTheme] = useState(false)

  const someValue = () => {
    // a slow function that uses the number state to compute and return a value
  }

  const toggleTheme = () => {
    setDarkTheme(t => !t)
  }

  const updateNumber = () => {
    setNumber(number + 1)
  }

  return (
    
) }


In this component, we have two states: number and darkTheme. And we have a variable, someValue which we’ll assume is a slow computation. And we have two functions for updating the state.

With this, when you execute the toggleTheme function, the component rerenders and someValue is recomputed again. And this happens when you also execute the updateNumber function. For our case, we only want someValue to be recomputed when the number state changes, as this value has no relationship with the theme, and as slow as it is, we want to improve the experience of our application.

With useMemo imported, we can do this:


...
  const someValue = useMemo(() => {
    // a slow function that uses the number state to compute and return a value
  }, [number])
...


This way, someValue will only be recomputed when the number (the dependency of the useMemo) changes. If it doesn’t, the memoized value will be used. Using this, we’ve improved the experience of our application.


For resolving reference conflicts between renders

When a component rerenders, existing objects and functions in the component will be redeclared, and just as you may already know with objects, two objects with the same content are different as they both point to different references in memory. Here’s what I mean:


const obj1 = { name: 'JavaScript' }
const obj2 = { name: 'JavaScript' }

obj1 !== obj2


Reference conflicts can happen in React components just like this example:


function App() {
  const [number, setNumber] = useState(0)
  const [darkTheme, setDarkTheme] = useState(false)

  const someValue = () => {
    // a slow function that uses the number state to compute and return a value
  }

  const toggleTheme = () => {
    setDarkTheme(t => !t)
  }

  const updateNumber = () => {
    setNumber(number + 1)
  }

  const themeClasses = {
    primaryColor: darkTheme ? '#333' : 'white'
  }

  useEffect(() => {
    console.log('themeClasses changed')
  }, [themeClasses])

  return (
    
) }


I introduced a themeClasses object with the primaryColor property that is different for light and dark theme. I also added a useEffect hook that simply logs “themeClasses changed” when the themeClasses object (the dependency) changes.

What we would expect from this is that, when the theme changes, the primaryColor property changes, thereby changing the themeClasses object and the log, “themeClasses changed”. But we get is different. If you try this on your browser, you’ll get “themeClasses changed” when you change the theme state, and also when you change the number state. Here’s why.

The themeClasses object is redeclared when the state changes. And as I explained earlier, the themeClasses object in the first render IS NOT EQUAL to the themeClasses object in the second render. To the useEffect hook, the object has changed, so the callback is run again.

This is where the useMemo hook comes in again. We can memoize the themeClasses object and only redeclare it when the darkTheme state changes, here’s how:


...
  const themeClasses = useMemo(() => {
    return {
        primaryColor: darkTheme ? '#333' : 'white'
    }
  }, [darkTheme])
...


With this in place, the useEffect hook will only run when the darkTheme state changes.


Do not use useMemo all the time

We’ve seen how relevant the useMemo hook is but, don’t use it every time. “This value doesn’t depend on this state…hmm..useMemo it is”…no!!!!

As helpful as useMemo is, you also need to understand that this hook is using some part of your memory to store these values. If you use useMemo everywhere in your application. this will use up more resources in memory and can negatively impact your application.

For computed values that are not slow or expensive, there’s no harm in recomputing them. For change in object references that do not affect your application, there’s no need memoizing them. Only use this hook where you actually need it to optimize your app.


Conclusion

In this article, we’ve seen how the useMemo hook works, it’s relevance and two use cases where you can optimize your application with the hook. We’ve also seen why you shouldn’t use this hook all the time / everywhere in your application.

You can also check out the useCallback hook which works similarly to this, but a bit differently.