How to Write Better React Code With useMemo
By: Caelin Sutch
Tags: React, Programming, Software Developmen, Reactjs, Web Development

When React hooks were introduced in React v16.8, developers were finally given the ability to manage state in functional components by using hooks like useState , useEffect , and others. In this article, we’ll be looking at the React hook useMemo and how we can use it to write faster React code.

Photo by Filiberto Santillán on Unsplash

To look at why useMemo even exists, we’ll first be looking at how rendering works.

Function Equality and Expensive Operations

useMemo at its core seeks to solve two problems, function equality and expensive operations.

During the lifecycle of a component, React re-renders the component whenever an update is made. This means that React will rebuild all the functions and variables in the React component, potentially a very expensive operation for more complex React components.

Objects in Javascript are by default unique. For example, lets take a look at this code:

Here, we have two objects, x and y , that have the exact same structure. However, when compared with Javascript they aren’t the same value!

When React checks for changes in a component, due to this object equality issue, it may be unnecessarily re-rendering the component tree due to perceived changes in objects, when in reality the object has the exact same values.

This is where a technique called memoization comes in.

What is Memoization?

Memoization is similar to caching an operation or value. For example, lets say we have a function that computes 1+1 and returns 2 . If we memoize this function, next time it uses the function to calculate 1+1 , it will remember that 1+1 is 2 without ever re-running the function!

This can be incredibly powerful for speeding up complex operations.

useMemo

From the official React documentation, useMemo looks like this:

const memoizedValue = React.useMemo(() => computeExpensiveValue(a, b), [a, b]);

Note that we pass in a function, in this case computeExpensiveValue , and a dependency array [a, b] . The dependencies are similar to arguments for the function, they’re what useMemo watches to determine whether or not it should run. When there’s no changes to a or b , useMemo won’t run and instead return the stored result.

This can be optimal if the wrapped function is incredibly expensive.

Lets take a look at a real world example:

const complexList = React.useMemo(() =>

list.map(item => ({

...item,

expensiveValueOne: expensiveFunction(props.first),

expensiveValue2: anotherPriceyFunction(props.second)

})), [list]

)

In this case, we’re using the useMemo hook to convert a list into a list of objects. On first render, this function will run, blocking the main thread. However, on every subsequent render, unless list changes, we can reuse the same value and not run the expensive functions again.

When to use useMemo

When doing any React optimization, ensure that you fully write and revise the code to see if you can optimize it. useMemo can actually hurt performance if used incorrectly.

Profiling your React application can be a great way to ensure there’s a measurable impact from implementing useMemo ,

Using the right hook for the job

useMemo isn’t the only React hook, there’s also useCallback , useRef , and useEffect .

The useCallback hook, which I wrote an article on, is very similar to useMemo but it returns a memoized function instead of a memoized value.

If your dependency array is empty or contains values that change on every render, there’s no chance for useMemo to properly memoize values and there will be no performance gain.

Don’t use useMemo to fire off any asynchronous values, instead you should use useEffect , useMemo should be used with pure functions.

Conclusion

The useMemo hook can be incredibly powerful for improving your React applications performance when used properly. By memoizing an expensive function, we can save the output value and make that function appear to run instantaneously. However, useMemo adds its own overhead, and should only be used when there’s a clear optimization benefit.

Keep in Touch

There’s a lot of content out there and I appreciate you reading mine. I’m a undergraduate student at UC Berkeley in the MET program and a young entrepreneur. I write about software development, startups, and failure (something I’m quite adept at). You can signup for my newsletter here or check out what I’m working on at my website.

Feel free to reach out and connect with me on Linkedin or Twitter, I love hearing from people who read my articles :)