useMemo
Caches the result of an expensive computation between re-renders, recomputing only when dependencies change.
Signature
const memoizedValue = useMemo<T>(factory: () => T, dependencies: any[])Parameters
| Parameter | Type | Description |
|---|---|---|
| factory | () => T | A function that computes a value. React calls this function during the initial render and re-calls it only when dependencies change. |
| dependencies | any[] | An array of reactive values. The factory re-runs when any dependency changes (compared with Object.is). |
Return Value
The cached return value of the factory function. Returns the previously computed value if dependencies haven't changed.
Examples
import { useState, useMemo } from 'react';
function ProductList({ products }: { products: { name: string; price: number }[] }) {
const [search, setSearch] = useState('');
const [sortBy, setSortBy] = useState<'name' | 'price'>('name');
const filtered = useMemo(() => {
console.log('Filtering...');
return products
.filter(p => p.name.toLowerCase().includes(search.toLowerCase()))
.sort((a, b) => sortBy === 'price' ? a.price - b.price : a.name.localeCompare(b.name));
}, [products, search, sortBy]);
return (
<div>
<input value={search} onChange={e => setSearch(e.target.value)} />
<p>{filtered.length} results</p>
</div>
);
}import { useMemo } from 'react';
function Chart({ data, width, height }: {
data: number[];
width: number;
height: number;
}) {
const config = useMemo(() => ({
dimensions: { width, height },
scale: { x: width / data.length, y: height / Math.max(...data) },
colors: { line: '#3b82f6', fill: 'rgba(59,130,246,0.1)' },
}), [data, width, height]);
// config has a stable reference, safe to pass to memoized children
return <CanvasChart config={config} />;
}import { useState, useMemo } from 'react';
interface CartItem { id: string; name: string; price: number; qty: number }
function CartSummary({ items }: { items: CartItem[] }) {
const summary = useMemo(() => {
const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0);
const tax = subtotal * 0.08;
const shipping = subtotal > 100 ? 0 : 9.99;
return { subtotal, tax, shipping, total: subtotal + tax + shipping };
}, [items]);
return (
<div>
<p>Subtotal: ${summary.subtotal.toFixed(2)}</p>
<p>Tax: ${summary.tax.toFixed(2)}</p>
<p>Shipping: {summary.shipping === 0 ? 'Free' : `$${summary.shipping}`}</p>
<p><strong>Total: ${summary.total.toFixed(2)}</strong></p>
</div>
);
}Common Pitfalls
Wrapping trivial computations in useMemo — the overhead of memoization can exceed the cost of the computation itself.
Mutating dependency values between renders, causing useMemo to miss changes.
Using useMemo as a semantic guarantee — React may discard cached values to free memory, so your code must still work without it.
Depending on an unstable reference (e.g., an inline object) in the dependency array, which recreates every render.
Understanding useMemo
useMemo is a React hook that caches the result of a computation between renders. It's designed for expensive calculations that shouldn't re-run on every render — things like filtering large lists, complex mathematical transformations, or creating derived data structures. By specifying dependencies, you tell React when the cached result should be recomputed.
Under the hood, useMemo stores both the computed value and the dependency array from the last render. On each subsequent render, React compares the current dependencies with the stored ones using Object.is. If all dependencies are the same, React returns the cached value without calling the factory function. This comparison is fast — O(n) where n is the number of dependencies — making it efficient for most use cases.
A key use case for useMemo beyond computation caching is creating stable object references. When you pass an object as a prop to a memoized child component, creating it inline means a new reference every render. Wrapping the object creation in useMemo ensures the reference stays stable when the underlying data hasn't changed, allowing React.memo to skip re-renders.
React explicitly warns in the documentation that useMemo is a performance optimization, not a semantic guarantee. The framework reserves the right to discard cached values (for example, during offscreen rendering or memory pressure), so your code must produce correct results even if useMemo recomputes on every render. Think of it as a hint to React, not a contract. If your computation has side effects, use useEffect instead.
Related Hooks
useCallbackReturns a memoized version of a callback function that only changes when its dependencies change. Prevents unnecessary re-renders of child components that receive callbacks as props.
useRefCreates a mutable ref object that persists across renders without triggering re-renders when its value changes. Commonly used for DOM access and storing mutable instance variables.
useDeferredValueDefers updating a part of the UI to keep the rest responsive. Returns a value that may lag behind during urgent updates, allowing non-critical UI to render at a lower priority.
More Performance Hooks
Explore All React Hooks
Browse our complete reference of 19 React hooks with signatures, examples, pitfalls, and in-depth explanations.