useMemo vs useCallback
useMemo memoizes a computed VALUE, useCallback memoizes a FUNCTION reference. Both use dependency arrays to control when recalculation happens.
Side-by-Side Comparison
| Feature | useMemo | useCallback |
|---|---|---|
| What it memoizes | A computed value | A function reference |
| Returns | The cached result | The cached function |
| Primary use case | Expensive computations | Stable callback references |
| Works with React.memo | Indirectly (via stable values) | Directly (stable function props) |
| Equivalent | useMemo(() => value, deps) | useMemo(() => fn, deps) |
Code Examples
useMemo
- Memoizes the RETURN VALUE of a function
- Recalculates only when dependencies change
- Avoids expensive recomputation on every render
- Returns the cached value, not a function
function ProductList({ items, filter }) {
// Only recalculates when items or filter change
const filtered = useMemo(
() => items.filter(i => i.name.includes(filter)),
[items, filter]
)
return filtered.map(item => <Item key={item.id} item={item} />)
}useCallback
- Memoizes the FUNCTION ITSELF (its reference)
- Returns the same function reference between renders
- Useful when passing callbacks to memoized children
- useCallback(fn, deps) === useMemo(() => fn, deps)
function Parent({ id }) {
// Same function reference unless id changes
const handleClick = useCallback(
() => { console.log('Clicked', id) },
[id]
)
// Child won't re-render if wrapped in React.memo
return <MemoizedChild onClick={handleClick} />
}When to Use Which
useMemo
Expensive calculations (filtering/sorting large lists), deriving data from props/state, creating objects/arrays passed as props to memoized children.
useCallback
Callbacks passed to React.memo children, event handlers used in useEffect dependency arrays, functions passed to custom hooks.
Common Mistakes
- Using useMemo for cheap operations — the memoization overhead can exceed the computation cost
- Forgetting that useCallback is useless without React.memo on the child component
- Including unstable references in the dependency array — defeats the purpose of memoization
Interview Questions
When is useMemo actually harmful?
When the computation is trivial (simple math, string concatenation). Memoization adds memory overhead and dependency comparison cost. Only use it when profiling shows the computation is expensive enough to justify caching.
Why is useCallback useless without React.memo?
Without React.memo, the child component re-renders whenever its parent re-renders regardless of prop changes. useCallback preserves function identity, but that only matters if something is actually checking for reference equality — which React.memo does.
How does the React Compiler change useMemo/useCallback?
React Compiler (React Forget) automatically memoizes values and callbacks, making manual useMemo/useCallback unnecessary. It analyzes your code at build time and inserts memoization where beneficial.