useMemo & Computed Values
MeduseMemo caches the result of an expensive computation between re-renders, recomputing only when its dependencies change. It prevents unnecessary recalculations and maintains referential stability for objects and arrays passed as props or used in dependency arrays.
Interactive Visualization
Key Points
- Accepts a function and dependency array, returns the memoized result
- Only recomputes when a dependency changes (shallow comparison)
- Primary use: skip expensive recalculations like sorting or filtering large lists
- Secondary use: maintain stable object/array references for React.memo or effect dependencies
- Not free: has overhead from dependency comparison and memory for cached values
- React may drop the cache in the future, so code must work without it
Code Examples
Expensive Computation
import { useMemo, useState } from 'react' interface Product { id: string name: string price: number category: string } function ProductList({ products }: { products: Product[] }) { const [filter, setFilter] = useState('') const [sortBy, setSortBy] = useState<'name' | 'price'>('name') const filteredAndSorted = useMemo(() => { const filtered = products.filter((p) => p.name.toLowerCase().includes(filter.toLowerCase()) ) return filtered.sort((a, b) => sortBy === 'price' ? a.price - b.price : a.name.localeCompare(b.name) ) }, [products, filter, sortBy]) return ( <div> <input value={filter} onChange={(e) => setFilter(e.target.value)} /> <button onClick={() => setSortBy('price')}>Sort by Price</button> {filteredAndSorted.map((p) => ( <div key={p.id}>{p.name}: ${p.price}</div> ))} </div> ) }
Filtering and sorting only recompute when products, filter, or sortBy change, not on every render from unrelated state updates
Stable Reference for Child Components
import { useMemo } from 'react' interface ChartData { labels: string[] values: number[] } interface DashboardProps { revenue: number[] months: string[] } function Dashboard({ revenue, months }: DashboardProps) { // Without useMemo, this creates a new object every render, // causing MemoizedChart to re-render unnecessarily const chartData: ChartData = useMemo( () => ({ labels: months, values: revenue }), [months, revenue] ) return <MemoizedChart data={chartData} /> }
useMemo keeps the same object reference between renders so memoized children can skip re-rendering via shallow prop comparison
Common Mistakes
- Wrapping every computation in useMemo even when the cost is trivial
- Omitting dependencies or including stale references in the dependency array
- Using useMemo where useCallback is more appropriate for memoizing functions
Interview Tips
- Explain that useMemo is an optimization, not a semantic guarantee
- Discuss when NOT to use useMemo: simple calculations, primitive values, rarely changing data
- Know that React may drop memoized values in the future to free memory