[React][Hook] Optimize Performance with useMemo and Memoization
Learn how memoization works with useMemo so heavy filters do not re-run when unrelated state like dark mode changes - and when not to wrap everything.

1. Environment
- OS: Windows 11 / macOS
- Frontend library: React.js (v18+)
- Core concept: React Hooks (
useMemo, memoization) - IDE: Visual Studio Code (VS Code)
2. Problem
This post digs into the real reason useMemo exists: memoization. We look at how it blocks pointless recalculation whenever state changes, and how that can lift frontend performance.
Related: Correct use of useEffect vs useMemo
3. Cause
When any state inside a React component changes, React re-runs the whole component function from top to bottom (a re-render). That simple, powerful rule can also cause surprising slowdowns.
Imagine one component that both runs a heavy calculation over 10,000 users and has a button that only toggles dark/light theme:
import { useState } from 'react';
function UserDashboard({ users }) {
const [isDarkMode, setIsDarkMode] = useState(false);
// Problem: this runs on every render
const activeUsers = users.filter((user) => {
console.log('Running an expensive calculation...');
return user.isActive;
});
return (
<div className={isDarkMode ? 'dark' : 'light'}>
<button onClick={() => setIsDarkMode(!isDarkMode)}>Toggle theme</button>
<p>Active users: {activeUsers.length}</p>
</div>
);
}
What happens when the user clicks Toggle theme?
Only the background should change - but because isDarkMode changed, React re-reads the entire component. Every theme click re-filters 10,000 users and loads the UI for no good reason.
4. Solution
1) What is memoization?
Memoization means: write down a hard result once, then reuse it instead of computing again when the inputs are the same.
If you calculated 12345 × 67890 = 838102050 yesterday, and someone asks for the same product today, you read the note - you do not multiply again.
2) Fix it with useMemo
The key is the dependency array [users]. It tells React:
“Recalculate
activeUsersonly whenuserschanges. Ifusersis unchanged and something else (likeisDarkMode) caused the re-render, do not recalculate - reuse the cached value.|–
import { useState, useMemo } from 'react';
function UserDashboard({ users }) {
const [isDarkMode, setIsDarkMode] = useState(false);
// Recalculate only when users changes
const activeUsers = useMemo(() => {
console.log('Running an expensive calculation...');
return users.filter((user) => user.isActive);
}, [users]); // dependency array
return (
<div className={isDarkMode ? 'dark' : 'light'}>
<button onClick={() => setIsDarkMode(!isDarkMode)}>Toggle theme</button>
<p>Active users: {activeUsers.length}</p>
</div>
);
}
After this change, you can toggle the theme a hundred times and the heavy filter still runs only when users actually changes.
5. Summary
Wrapping every variable in useMemo because “it improves performance|–is a bad idea.
Caching a value and comparing the dependency array on every render also costs memory and CPU. A trivial line like const fullName = firstName + lastName can finish faster than the bookkeeping of memoization.
Use useMemo selectively for work that is actually expensive - list filtering/sorting over large arrays, or heavy math. If a stable, costly calculation is slowing renders, that is when this Hook earns its place.


