useMemo
Cache the result of an expensive calculation between renders.
Syntax
const result = useMemo(() => compute(a, b), [a, b]);useMemo memoizes (caches) the result of a calculation. React recomputes it only when one of its dependencies changes, skipping expensive work on other renders.
When to use it
- An expensive computation (sorting or filtering a big list) that reruns on every render.
- Keeping a stable object or array reference so a memoized child does not re-render.
Do not overuse it — for cheap calculations the overhead is not worth it.
Example
import { useMemo, useState } from 'react';
function ProductList({ products }) {
const [query, setQuery] = useState('');
const filtered = useMemo(
() => products.filter((p) => p.name.includes(query)),
[products, query]
);
return (
<div>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
<ul>{filtered.map((p) => <li key={p.id}>{p.name}</li>)}</ul>
</div>
);
}When to use it
- A data table memoizes the result of filtering and sorting 10,000 rows so the expensive computation only reruns when the filter criteria actually change, not on every unrelated re-render.
- A chart component uses useMemo to derive formatted axis labels from raw timestamps once, avoiding repeated date-parsing across every render triggered by tooltip hover state.
- A tree-view component memoizes the recursive tree-building computation so expanding one node does not recompute the entire tree structure.
More examples
Memoize filtered list
Wraps the filter call in useMemo so it only reruns when products or search changes, not on unrelated state updates.
import { useState, useMemo } from 'react';
function ProductList({ products }) {
const [search, setSearch] = useState('');
const filtered = useMemo(
() => products.filter(p => p.name.toLowerCase().includes(search.toLowerCase())),
[products, search]
);
return (
<>
<input value={search} onChange={e => setSearch(e.target.value)} />
<ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>
</>
);
}Memoize expensive computation
Caches the result of three aggregate calculations so they are not recomputed every render when other state changes.
import { useMemo } from 'react';
function Stats({ values }) {
const { sum, avg, max } = useMemo(() => {
const sum = values.reduce((a, b) => a + b, 0);
return { sum, avg: sum / values.length, max: Math.max(...values) };
}, [values]);
return <p>Sum: {sum}, Avg: {avg.toFixed(2)}, Max: {max}</p>;
}Stable object reference for child
Uses useMemo to keep the config object reference stable across tab changes so the memoized Chart does not re-render.
import { useState, useMemo, memo } from 'react';
const Chart = memo(({ config }) => <div>Chart: {config.color}</div>);
function Dashboard({ data }) {
const [tab, setTab] = useState('sales');
const chartConfig = useMemo(() => ({ color: 'blue', data }), [data]);
return (
<>
<button onClick={() => setTab('sales')}>Sales</button>
<Chart config={chartConfig} />
</>
);
}
Discussion