Make Use of useMemo Like You Mean It
Muhammad Athar

If you've read Did You Know useCallback Can Actually Do This? you already understand the core idea behind memoization in React — keeping a reference stable between renders so React doesn't do unnecessary work.
useMemo is the same idea applied to values instead of functions.
In Alex Chen's Why React.memo Doesn't Always Help there's this pattern:
If you understood useCallback after the last article, useMemo will click in about two minutes. If you're coming to this fresh — stay with me, we'll get there.
The problem it solves
Every time a React component re-renders, every line of code inside it runs again. Every variable is recalculated. Every function is redefined. Every expression is re-evaluated.
Most of the time that's fine — these operations are fast. But occasionally you have a calculation that's genuinely expensive. Filtering a list of ten thousand items. Sorting a complex dataset. Transforming a large array into a different structure. Running that calculation on every render — including renders that have nothing to do with the data being processed — is wasteful.
useMemo lets you say: "only recalculate this when the inputs actually change."
React runs expensiveCalculation(data) on the first render and stores the result. On subsequent renders, if data hasn't changed, React skips the calculation entirely and returns the stored result. If data changes, React re-runs the calculation and stores the new result.
That stored result is the memo. That's the whole thing.
The basic shape
Three parts:
- A function that returns the value you want to memoize — not the value itself, a function that produces it
- A dependency array — the values that, when changed, should trigger a recalculation
- The return value — whatever the function returns, stored and reused between renders
Same dependency array logic as useEffect and useCallback. When any value in the array changes, the function re-runs. When nothing changes, the cached result comes back.
useMemo vs useCallback — the one-line difference
These two hooks confuse people because they look almost identical.
useCallback(fn, deps) is shorthand for useMemo(() => fn, deps).
They're the same mechanism. useCallback is just the version optimised for the common case of memoizing a function. Use useCallback for functions, useMemo for everything else.
Building something real: a filterable product list
Here's a complete product filter component — the kind you see on every e-commerce site. A search input, a category filter, and a list of products that updates as you type.
The expensive part: filtering and sorting a large array on every keystroke. Without useMemo, this runs on every render — including renders triggered by unrelated state changes. With useMemo, it only runs when the filter inputs actually change.
Two places useMemo is doing real work here:
filteredProducts — the filter + sort chain runs only when search, category, or sort changes. Notice cartCount is state in this same component. Every time the user clicks "Add to cart", the component re-renders — but filteredProducts doesn't recalculate. Without useMemo it would.
averagePrice — a derived value that depends on filteredProducts. Because filteredProducts is itself memoized, averagePrice only recalculates when the filtered list actually changes. One memo depending on another — a clean chain.
When useMemo is not the answer
Same caveat as useCallback — memoization has a cost. React stores the previous value, runs the dependency comparison on every render, and returns the cached result if nothing changed. For cheap calculations, this overhead outweighs the savings.
useMemo is worth it when:
- The calculation is genuinely slow — filtering/sorting large arrays, complex transformations, expensive mathematical operations
- The value is a dependency in another hook — preventing
useEffector anotheruseMemofrom re-running unnecessarily - The value is passed as a prop to a
React.memocomponent — keeping the prop reference stable
It is not worth it for:
If the calculation takes less than a millisecond, write it inline. Profile first, memoize second.
The pattern to remember
useMemo is about skipping work you've already done when the inputs haven't changed.
Where this leads
useRef — stores a value that persists across renders without triggering a re-render, and without the memoization overhead of useMemo. The right tool when you need to hold a DOM reference or a previous value. Coming up next in the series.
React.memo — the component-level version of useMemo. Wraps a whole component so it only re-renders when its props change. useMemo and React.memo work best together — memoized values passed as props to memoized components. Alex covers this in detail in Why React.memo Doesn't Always Help.
useReducer — when your state logic gets complex enough that multiple useState calls feel tangled, useReducer is the next tool to learn. It pairs naturally with useMemo for managing derived state from complex state objects.
This article was prompted by the React Foundations series — particularly How to Build a Custom Hook That Actually Earns Its Abstraction and Did You Know useCallback Can Actually Do This?. If the filterable product list above sparked an idea for something you're building — that's the point.
Muhammad Athar is the founder and engineer behind DesignDev.io. He writes the "From the Builder" series — concept explainers triggered by the site's own articles, always grounded in something you can actually build.
Photo by Árpád Czapp on Unsplash

