The useMemo Hook and Expensive Computations0%

The useMemo Hook and Expensive Computations

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

The useMemo Hook and Expensive Computations

1. What is useMemo?

While useCallback caches a function definition, useMemo caches the result of an expensive computation.

$$\text{CachedResult} = \text{useMemo}(\text{calculateValue}, \text{dependencies})$$

On initial render, useMemo calls your calculation function and stores the result. On subsequent renders, React checks if the dependencies have changed:

  • If dependencies are unchanged, React returns the cached result without running the calculation again.
  • If dependencies have changed, React re-executes the calculation, stores the new result, and returns it.
Output
Render 1:
useMemo(() => expensiveCalculation(data), [data]) ──► Runs calculation (takes 80ms) ──► Returns result
 
Render 2 (unrelated state changed, data is same):
useMemo(...) ──► Returns cached result instantly (takes 0.001ms)!

2. Practical Example: Filtering 10,000 Complex Records

JSX
import React, { useState, useMemo } from 'react';
 
// Simulated heavy calculation
function performComplexAnalytics(transactions, threshold) {
console.log('Running heavy analytics calculation...');
// Intensive array filtering, grouping, and statistical variance calculation
return transactions
.filter(t => t.amount >= threshold)
.reduce((acc, t) => acc + t.amount, 0);
}
 
export default function AnalyticsDashboard({ transactions }) {
const [threshold, setThreshold] = useState(100);
const [theme, setTheme] = useState('light');
 
// ✅ useMemo caches the computed total:
// When 'theme' changes, this expensive calculation is COMPLETELY SKIPPED!
const totalVolume = useMemo(() => {
return performComplexAnalytics(transactions, threshold);
}, [transactions, threshold]); // Only recompute when transactions or threshold changes!
 
return (
<div className={`analytics-box theme-${theme}`}>
<button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
Toggle Dashboard Theme
</button>
 
<h3>Analyzed Volume: ${totalVolume.toLocaleString()}</h3>
<input
type="range"
min={0}
max={1000}
value={threshold}
onChange={(e) => setThreshold(Number(e.target.value))}
/>
</div>
);
}

3. Difference Between useMemo and useCallback

Engineers often confuse the two hooks:

  • useMemo: Invokes the function and caches its return value (useMemo(() => computeVal(), deps)).
  • useCallback: Caches the function itself without executing it (useCallback(() => doSomething(), deps)).

In fact, useCallback(fn, deps) is simply syntactic sugar for:

JavaScript
useMemo(() => fn, deps);

4. When Is a Calculation Truly "Expensive"?

Most everyday JavaScript operations (mapping 50 array elements, basic math, string concatenations) execute in fractions of a microsecond. Wrapping them in useMemo adds more overhead than it saves!

How to measure:

Use console.time() or the React DevTools Profiler:

JavaScript
console.time('filter');
const results = filterData(items);
console.timeEnd('filter');

If the calculation takes less than 1ms, memoization is unnecessary. If it takes 10ms or more, wrapping it in useMemo delivers substantial real-world responsiveness gains.


Interactive Quiz

Practice Quiz

Question 1
What does the useMemo hook cache across component renders?
Question 2
How does useMemo differ from useCallback?
Question 3
When is wrapping a calculation in useMemo genuinely justified?
Question 4
If useMemo(() => computeTotal(items), [items]) has an unchanged items array, what does React do during render?
Question 5
What is the equivalent of useCallback(fn, deps) expressed using useMemo?
Next Lesson

Extracting Reusable Business Logic into Custom Hooks

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext