useMemo Hook
In this page:
Memoizing an Expensive Calculation
useMemo(calculateValue, dependencies) runs calculateValue and caches its result. On future renders, if the dependencies haven't changed, React reuses the cached result instead of recalculating it, saving the cost of an expensive computation.
Note: Reach for useMemo specifically when a calculation is measurably slow -- not as a default habit for every derived value.
Warning: useMemo still runs the calculation once per unique set of dependencies -- it doesn't make the first calculation free, only subsequent identical ones.
Example: Memoizing an Expensive Calculation
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function ExpensiveList({ items }) {
const sorted = React.useMemo(() => {
console.log("Sorting...");
return [...items].sort();
}, [items]);
return <ul>{sorted.map((item, i) => <li key={i}>{item}</li>)}</ul>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<ExpensiveList items={["banana", "apple", "cherry"]} />);
</script>
</body>
</html>
How the Dependency Array Controls Recalculation
Just like useEffect, useMemo takes a dependency array as its second argument. React compares each dependency to its previous value, and only re-runs the calculation function if at least one of them has changed since the last render.
Note: List every value the calculation function actually reads, the same way you would for useEffect's dependency array.
Warning: An empty dependency array [] means the value is only ever calculated once, which is wrong if the calculation depends on props or state that can change.
Example: How the Dependency Array Controls Recalculation
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function PriceCalculator({ quantity, price }) {
const total = React.useMemo(() => {
console.log("Recalculating total...");
return quantity * price;
}, [quantity, price]);
return <p>Total: ${total}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<PriceCalculator quantity={3} price={9.99} />);
</script>
</body>
</html>
When NOT to Use useMemo
For cheap calculations -- simple arithmetic, short string formatting -- the overhead of useMemo's own bookkeeping can outweigh any benefit. useMemo is a targeted optimization tool for genuinely expensive work, not a default wrapper for every derived value.
Note: If you're unsure whether a calculation is 'expensive enough' to memoize, it usually isn't -- add useMemo only once you've noticed an actual performance problem.
Warning: Wrapping trivial calculations in useMemo everywhere makes code harder to read without any measurable performance gain.
Example: When NOT to Use useMemo
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function SimpleGreeting({ name }) {
// No useMemo needed here -- this is trivially cheap
const greeting = `Hello, ${name}!`;
return <p>{greeting}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<SimpleGreeting name="Sam" />);
</script>
</body>
</html>
- Wrapping every single calculation in useMemo, even cheap ones, adding overhead without real benefit.
- Forgetting to list a value used inside the memoized calculation in the dependency array.
- Expecting useMemo to prevent a component from re-rendering -- it only memoizes a calculated VALUE, not the render itself.
- useMemo caches the result of an expensive calculation between renders.
- It only recalculates when one of its listed dependencies changes.
- It's meant for genuinely expensive computations, not for optimizing everything by default.
- Overusing useMemo can add complexity without meaningful performance benefit.
Available since React 16.8, when Hooks were introduced.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: