useMemo caches a value between renders. Pass it a calculation and a dependency array: React returns the previous value while the dependencies remain unchanged, and runs the calculation again when one changes. Use it for expensive calculations or to keep a value referentially stable—not as a default wrapper around every expression. section 3.2.4 section 3.4
Two useful fits:
- Cache derived data. An employee list filtered by temporary-worker status needs recalculation only when the source list or filter changes: useMemo(() => employeeList.filter(({ isTemporary }) => showTempOnly ? isTemporary : true), [employeeList, showTempOnly]). section 3.2.4
- Stabilize a prop for a memoized component. Constructing ["Complete todo list", ...items] inline creates a new array on each render, defeating the child’s memoization. Use useMemo(() => ["Complete todo list", ...items], [items]) instead. section 3.2.3
- Cache a JSX fragment when the unchanged work sits inside a parent rather than a separate component. Extracting and memoizing a child component is another option; choose the clearer structure. section 3.2.2
Listing 3.11 Memoized filtering
import { useMemo, useState } from "react"; #1
function Employees({ employeeList }) {
const [showTempOnly, setShowTempOnly] = useState(false);
const filteredList = useMemo( #2
() => #3
employeeList.filter(({ isTemporary }) => #3
showTempOnly ? isTemporary : true #3
), #3
[employeeList, showTempOnly] #4
);
return (
<section>
<h1>Employees</h1>
<label>
<input
type="checkbox"
onChange={() => setShowTempOnly((f) => !f)}
/>
Show temp only?
</label>
<ul>
{filteredList.map(({ id, name, salary, isTemporary }) => (
<li key={id}>
{name}: {salary} {isTemporary && "(temp)"}
</li>
))}
</ul>
</section>
);
}
function App() {
const employeeList = [
{ name: "Bugs Bunny", salary: "$20,000", isTemporary: false },
{ name: "Daffy Duck", salary: "$15,000", isTemporary: false },
{ name: "Porky Pig", salary: "$17,000", isTemporary: true },
...
];
return <Employees employeeList={employeeList} />;
}
export default App;
The employee-list implementation shows the calculation and both dependencies together. section 3.2.4
Listing 3.9 A to-do list with a memoized fixed item (excerpt)
...
function Todo() {
...
const allItems = useMemo(() => #1
["Complete todo list", ...items], #1
[items]); #1
return ( #1
<main>
<Items items={allItems} /> #2
...
</main>
);
}
...
The to-do excerpt shows how to keep an array prop stable for a memoized child. section 3.2.3
Keep the dependency array accurate: it controls when the cached result is replaced. For functions, useCallback expresses the corresponding intent more directly. Measure before adding memoization; its overhead and added complexity can outweigh the work it saves. section 3.2.4 section 3.4


