useMemo & useCallback

How to cache expensive calculations and preserve object references between renders to optimize your React applications.

React5 min readConcept 31 of 46

Caching Values and Functions

In React, every time a component re-renders, its entire function body executes from top to bottom. This means all local variables are re-calculated, and all local functions are re-defined in memory.

useMemo is a hook that caches the *result* of a calculation. It only re-calculates when its dependencies change.

useCallback is almost exactly the same, but it caches a *function definition* instead of a value.

The Two Main Use Cases

**1. Skipping Expensive Math:** If you are filtering an array of 10,000 items, you don't want to re-run that loop every time the user types in an unrelated text input. useMemo caches the filtered array.

**2. Preserving Referential Equality:** As we learned in React.memo, if you pass an object {} or a function () => {} as a prop to a memoized child, it breaks the memoization because {} !== {}. You must wrap the object in useMemo or the function in useCallback to ensure the memory address stays identical across renders.

Syntax and Dependency Arrays

Both hooks take two arguments: the thing to cache, and a dependency array (just like useEffect).

const sortedData = useMemo(() => heavySort(data), [data]);

const handleClick = useCallback(() => submit(id), [id]);

React will return the exact same cached value/function on subsequent renders, *unless* the variables in the dependency array have changed.

The Price of Re-calculation

Interact with the Dashboard below. It contains a 'Heavy Calculation' (simulated by artificially freezing the thread for 500ms). Notice what happens when you type in the unrelated input field with and without useMemo.

function Dashboard() { const [text, setText] = useState(""); const [data, setData] = useState([...]); // ❌ Re-runs EVERY time you type in the input! const processedData = heavyMath(data); return ( <> <input onChange={(e) => setText(e.target.value)} /> <HeavyChart data={processedData} /> </> ); }
heavyMath(data)(Takes 500ms to run)
CACHE DISABLED
useMemo Cache[data]

Notice how without useMemo, typing in the unrelated input forces the heavy calculation to re-run (spinning red gear). With useMemo enabled, typing safely pulls the result from the Cache (flashing green), bypassing the heavy math entirely.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What is the primary difference between `useMemo` and `useCallback`?
  2. 2Why is `useCallback` often required when passing functions to a child component wrapped in `React.memo`?
  3. 3Which of the following is a BAD use case for `useMemo`?

Remember this

  • useMemo caches the return value of a calculation.
  • useCallback caches a function definition.
  • Use them to skip expensive calculations (heavy math, large array methods).
  • Use them to preserve referential equality when passing props to React.memo.
  • Do NOT use them for simple, fast calculations. The caching mechanism itself has a performance cost.

Done with this concept?

Mark it complete to track your progress. No login needed.