You can improve both the performance and render speed of your components with the useMemo hook. For large apps or even small ones that make expensive calculations or HTTP requests, the useMemo
hook can make a huge difference in the speed of your application. So in this guide, I’m going to explain what situations useMemo
addresses and show you how to use it in your own apps.
Example of a “slow” component
The best way to understand useMemo
memoization is with an example of a slow application.
This example isn’t necessarily slow, but it could definitely benefit from memoization. Below, we have a component that displays a number of the Fibonacci sequence based on a given input. The function that finds the number in the sequence uses recursion, which is an expensive kind of operation that results in many layers of function calls on the call stack. So if you enter a large number, the performance will take a hit.
const findFibonacci = n => {
return (n < 3 ? 1 ; findfibonacci(n - 1) + findFibonacci(n - 2)); }; const Fibonacci = () => {
const [n, setN] = useState(1);
const [useless, setUseless] = useState(0);
const fibonacci = findFibonacci(n);
const onChange = e => setN(e.target.value);
const onClick = () => setUseless(prev => prev + 1);
return (
<>
<h2>{fibonacci}</h2>
<input type='number' onChange={onChange} />
<button onClick={onClick}>Click to re-render</button>
</>
);
};
It’s important to remember that any state change will cause a re-render, even a change in the useless
state! So if we were to click the button, which mutates the useless
state, it would also result in the fibonacci
variable being re-calculated even though the n
state hasn’t changed. The result will be the same.
The useMemo Hook and Memoization
With memoization, we can arrange so that expensive calculations (such as finding a number in the Fibonacci sequence) only occur when necessary – in this case, whenever the n
state is updated.
We can use the useMemo
hook to accomplish this. It accepts two parameters: a callback where you can perform your calculations, and a dependency array. Whenever any variable in the dependency array changes, the callback will run and the memoized value will update.
Let’s rewrite our component using useMemo
.
const findFibonacci = n => {
return (n < 3 ? 1 : findFibonacci(n - 1) + findFibonacci(n - 2)); }; const Fibonacci = () => {
const [n, setN] = useState(1);
const [useless, setUseless] = useState(0);
const fibonacci = useMemo(() => findFibonacci(n), [n]);
const onChange = e => setN(e.target.value);
const onClick = () => setUseless(prev => prev + 1);
return (
<>
<h2>{fibonacci}</h2>
<input type='number' onChange={onChange} />
<button onClick={onClick}>Click to re-render</button>
</>
);
};
You’ll notice that the only line that changed is where we assign the fibonacci
variable!
But now, with fibonacci
memoized, it will only re-evaluate when the n
state updates. So if we click the button, updating the useless
state, the component will re-render but it will use the memoized value of fibonacci
.
useMemo
is useful in a huge array of situations. It can be useful to memoize the results from an HTTP request, which is often an expensive operation.
Check out the documentation on the useMemo
hook for more information.
To learn React like a pro, head over to my YouTube channel, or start with my introduction to React.