useMemo() Hook⚡ Memoize expensive calculations ? Recompute only when needed
The React useMemo() Hook memoizes the result of a computation — it caches a calculated value and only recomputes it when one of its dependencies changes.
This is useful when you have expensive calculations (loops, filters, derived data, heavy transformations) that you don’t want to run on every render.
Think of useMemo as telling React: “Only recompute this value if something important changes.”
useMemo only when there is a measurable benefit.Basic syntax for useMemo():
// Memoize an expensive computation based on dependencies a and b
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Imagine a component that performs a very heavy calculation inside a large loop. Without useMemo, this calculation would re-run on every render.
// Component that memoizes a very expensive calculation
function ExpensiveCalculation({ number }) {
const expensiveValue = React.useMemo(() => {
console.log("Calculating...");
let total = 0;
for (let i = 0; i < 100000000; i++) {
total += number * 2;
}
return total;
}, [number]);
return (
<div>
<h4>Calculated Value: {expensiveValue}</h4>
</div>
);
}
useMemo callback.expensiveValue is cached until number changes.number will reuse the existing result, improving performance.useMemo is great for computing derived state, like filtered lists based on user input.
// Filter a list of users efficiently using useMemo
function FilterList() {
const [query, setQuery] = React.useState("");
const users = ["Alice", "Bob", "Charlie", "David", "Eve"];
const filtered = React.useMemo(() => {
console.log("Filtering...");
return users.filter((u) => u.toLowerCase().includes(query.toLowerCase()));
}, [query]);
return (
<div>
<input
placeholder="Search..."
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<ul>
{filtered.map((user) => (
<li key={user}>{user}</li>
))}
</ul>
</div>
);
}
filtered list is derived from users and the search query.query changes.useMemo + React.memo Child ComponentCombine useMemo with React.memo to prevent unnecessary re-renders of child components.
// Parent & child components optimized with useMemo and React.memo
const UserList = React.memo(({ users }) => {
console.log("UserList rendered");
return (
<ul>
{users.map((u) => (
<li key={u}>{u}</li>
))}
</ul>
);
});
function App() {
const [filter, setFilter] = React.useState("");
const [count, setCount] = React.useState(0);
const users = ["Anna", "Brian", "Chris", "Diana"];
const filteredUsers = React.useMemo(() => {
return users.filter((u) => u.toLowerCase().includes(filter.toLowerCase()));
}, [filter]);
return (
<div>
<input
placeholder="Filter users..."
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
<UserList users={filteredUsers} />
<button onClick={() => setCount(count + 1)}>
Increment ({count})
</button>
</div>
);
}
UserList is wrapped with React.memo, so it only re-renders when its users prop changes.filteredUsers is memoized using useMemo, based on the filter value.count does not cause UserList to re-render, improving efficiency.useMemo() vs useCallback()Both use a dependency array, but they memoize different things:
| Aspect | useMemo() | useCallback() |
|---|---|---|
| Purpose | Memoizes a computed value | Memoizes a function |
| Returns | Cached value | Stable callback reference |
| Common Use | Expensive calculations, derived data | Event handlers, callbacks passed to children |
| Recomputed When | Dependencies change | Dependencies change |
useMemo everywhere — it itself has a small overhead.useMemo for expensive logic (loops, filters, heavy calculations) — not for simple variables.useMemo with React.memo or useCallback to limit child re-renders.useMemo to memoize the computed result.useMemo so that the list is recomputed only when needed.React.memo, pass it a memoized value from useMemo, and verify that it does not re-render when unrelated state changes.useMemo from your examples and compare how many times computations and child components run using console.log().Goal: Understand how useMemo() improves performance by memoizing computational results so that React recalculates values only when dependencies change, not on every render.