useMemo and useCallback Real Use Cases
A practical guide to when useMemo and useCallback are actually needed, how they work, and how to use them effectively to avoid unnecessary renders in React.
useMemo and useCallback Real Use Cases
useMemo and useCallback help stabilize values between renders. They are not performance tools by default. Their real purpose is to prevent unnecessary renders caused by unstable object, function, or value identities.
Most components do not need them, but in certain scenarios they become essential for building predictable, efficient React applications.
1. Why Stability Matters in React
React re-renders a component when its props change identity. Certain values are recreated every render unless stabilized.
Unstable values include:
- objects
- arrays
- functions
Example:
<Chart options={{ dark: true }} />React sees a new object each render, which triggers re-rendering.
2. When to Use useMemo
useMemo caches a computed value across renders.
Stabilizing an object
const chartOptions = useMemo(() => {
return { dark: theme === "dark" };
}, [theme]);Expensive calculation
const sorted = useMemo(() => {
return [...items].sort((a, b) => a.value - b.value);
}, [items]);Only use useMemo when the computation is expensive or the identity must remain stable.
3. When NOT to Use useMemo
Avoid for simple values or micro optimizations.
Anti-pattern:
const doubled = useMemo(() => count * 2, [count]);This adds complexity without benefit.
4. When to Use useCallback
useCallback stabilizes function references between renders.
Example
const handleSelect = useCallback(() => {
setSelected(true);
}, []);Children receiving callbacks benefit from stable references.
5. useCallback vs useMemo
useMemo returns a value.
useCallback returns a function.
They behave the same internally.
6. Stabilizing Dependencies for useEffect
Unstable dependencies cause unnecessary effect executions.
Bad:
useEffect(() => {
loadData();
}, [filters]);Fix:
const stableFilters = useMemo(() => filters, [filters.id]);
useEffect(() => {
loadData();
}, [stableFilters]);7. Memoizing Child Components
Child
const Table = memo(function Table({ rows }) {
return <div>{rows.length}</div>;
});Parent
const rows = useMemo(() => data.map(mapper), [data]);
<Table rows={rows} />;Stable values + memoized children = predictable renders.
8. When Memoization Hurts Performance
Memoization has a cost.
Only use these hooks for:
- heavy child components
- expensive calculations
- stabilizing dependencies
- preventing render cascades
9. Real World Examples
- Large lists where children re-render too often
- Forms with many fields and handlers
- Tables or charts that accept complex config objects
- Components that receive callbacks from deeply nested parents
Final Thoughts
useMemo and useCallback are identity stabilization tools. They help React avoid unnecessary renders and keep components predictable. Use them purposefully, not by default.