What is the `useMemo` hook in React and when should it be used?
TL;DR
The useMemo hook in React is used to memoize expensive calculations so that they are only recomputed when one of the dependencies has changed. This can improve performance by avoiding unnecessary recalculations. You should use useMemo when you have a computationally expensive function that doesn't need to run on every render.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
What is the useMemo hook in React and when should it be used?
What is useMemo?
The useMemo hook is a built-in React hook that allows you to memoize the result of a function. This means that the function will only be re-executed when one of its dependencies changes. The primary purpose of useMemo is to optimize performance by preventing unnecessary recalculations.
Syntax
The syntax for useMemo is as follows:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- The first argument is a function that returns the value you want to memoize.
- The second argument is an array of dependencies. The memoized value will only be recomputed when one of these dependencies changes.
When should it be used?
Expensive calculations
If you have a function that performs a computationally expensive calculation, you can use useMemo to ensure that this calculation is only performed when necessary. Genuinely expensive work means things like filtering or sorting a large list, parsing a big payload, or running a heavy synchronous algorithm — not trivial arithmetic.
const filterAndSortLargeList = (items, query) => {// Genuinely expensive: scans every item and sorts the result.return items.filter((item) => item.name.toLowerCase().includes(query.toLowerCase())).toSorted((a, b) => a.name.localeCompare(b.name));};const MyComponent = ({ items, query }) => {const visibleItems = useMemo(() => filterAndSortLargeList(items, query),[items, query],);return <List items={visibleItems} />;};
Preserving referential equality for memoized children
This is the most common practical reason to reach for useMemo. Every render produces a new object/array literal, which breaks React.memo (or useEffect dependency) bailouts on a child. Memoizing the value keeps its reference stable across renders.
const Parent = ({ items }) => {// Without useMemo, `sortedItems` would be a new array on every render,// and `MemoChild` would re-render even when `items` is unchanged.const sortedItems = useMemo(() => [...items].sort((a, b) => a - b), [items]);return <MemoChild sortedItems={sortedItems} />;};const MemoChild = React.memo(function MemoChild({ sortedItems }) {return <ul>{/* ... */}</ul>;});
Note that useMemo on a value alone does not prevent the child from re-rendering — the child must also be wrapped in React.memo (or otherwise short-circuit). Also, [...items].sort(...) (or items.toSorted(...)) is used here because Array.prototype.sort mutates in place; mutating a prop is a bug waiting to happen.
Caveats
- Overuse: Overusing
useMemocan lead to more complex code without significant performance benefits. It should be used judiciously. - Dependencies: Make sure to correctly specify all dependencies. Missing dependencies can lead to stale values, while extra dependencies can lead to unnecessary recalculations.
- It is only a hint:
useMemois a performance hint, not a guarantee. React is allowed to throw away the cached value and recompute it (for example, to free memory). Never rely onuseMemofor correctness — only for optimization. - The React Compiler changes the calculus: As of 2026, the React Compiler is stable. When enabled, it auto-memoizes components and values for you, which largely removes the need to write
useMemo(anduseCallback) by hand. New codebases on the Compiler should reach foruseMemoonly for genuinely expensive work that the compiler cannot infer, or to satisfy a specific reference-equality requirement.
Further reading
- React documentation on
useMemo - When to useMemo and useCallback by Kent C. Dodds