React Performance06-06-202411 min read

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.