useMemo Hook
Overview
During a React re-render, the entire component function runs from top to bottom. If you have a slow, CPU-intensive mathematical calculation (like filtering a massive array of 100,000 items, or running a cryptographic hash), that calculation will run every single time the component re-renders. If the user is typing in a text box, the calculation runs on every keystroke, freezing the browser.
The `useMemo` hook solves this by 'memoizing' (caching) the result of a calculation.
You pass useMemo a function that performs the heavy math, and a Dependency Array. React will run the math once, cache the result, and return it. On subsequent renders, React checks the dependency array. If the dependencies haven't changed, React skips the math entirely and instantly returns the cached result.
Syntax
import { useState, useMemo } from 'react';
function DataAnalyzer({ rawData }) {
const [theme, setTheme] = useState('dark');
// 1. Without useMemo, this heavy loop runs every time 'theme' is toggled!
// const processedStats = runHeavyCalculations(rawData);
// 2. With useMemo, the calculation ONLY runs when 'rawData' changes.
// Toggling the theme instantly bypasses the math and uses the cached data.
const processedStats = useMemo(() => {
console.log("Running 500ms calculation...");
return runHeavyCalculations(rawData);
}, [rawData]); // Re-run ONLY if rawData changes
return (
<div className={theme}>
<button onClick={() => setTheme(t => t === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
<StatsDisplay stats={processedStats} />
</div>
);
}Common Pitfalls
- Using useMemo for cheap operations: Do not use
useMemofor simple operations likearray.map()on 10 items or basic string concatenations. Calling theuseMemohook and allocating the cache memory actually has a baseline performance cost. Caching cheap math is slower than just running the cheap math.
Interview Questions
useEffect and useMemo?useEffect is for executing side effects (like API calls) after the render is completely finished. useMemo is for caching the result of a mathematical calculation during the render phase so that the render itself happens faster.
useMemo help fix React.memo components that are breaking?Because React.memo does a shallow comparison, passing a newly created object like config={{ color: 'red' }} will cause the memoized child to re-render (since {} creates a new memory reference every render). You can use useMemo to cache the object itself (const config = useMemo(() => ({ color: 'red' }), [])), preserving its exact memory reference and allowing React.memo to work properly.
Real-World Example
Preserving Object References for Context: This is arguably the most important use case for useMemo in modern React. It is absolutely mandatory to memoize object values passed into Context Providers to prevent massive, app-wide render cascades.
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
// If we pass an inline object to the Context Provider:
// value={{ user, setUser }}
// EVERY consumer of this context will re-render whenever AuthProvider re-renders,
// because the object {} is technically a new reference every time.
// The Fix: Cache the object reference using useMemo!
const contextValue = useMemo(() => {
return { user, setUser };
}, [user]); // Only recreate the object if 'user' actually changes
return (
<AuthContext.Provider value={contextValue}>
{children}
</AuthContext.Provider>
);
}Check Your Knowledge
Test your understanding of useMemo Hook with these quick questions.