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.