If you've worked with React, you've likely seen these two hooks show up in code reviews and wonder whether you actually need them.
The short answer: sometimes yes, often no.
The one-line distinction
-
useMemoremembers a value -
useCallbackremembers a function
That's the entire mental model. Everything else follows from this.
Why do they exist?
Every time a React component re-renders, variables and functions inside it are recreated from scratch — even if nothing logically changed. Most of the time, this is fine. But it becomes a problem when those recreated values are passed as props.
function Parent() {
const handleClick = () => console.log("clicked");
return <Child onClick={handleClick} />;
}
On every render, handleClick is a brand new function. To React, a new function means a changed prop — so Child re-renders, even though the behavior is identical.
useCallback fixes this by holding onto the same function reference across renders:
const handleClick = useCallback(() => {
console.log("clicked");
}, []);
Same idea applies to derived data. This runs on every render:
const filtered = items.filter(item => item.active);
useMemo runs it only when the dependency changes:
const filtered = useMemo(() => items.filter(item => item.active), [items]);
When to actually use them
Use useCallback when passing functions to child components, particularly ones wrapped in React.memo.
Use useMemo when performing expensive computations or transforming large datasets.
When to skip them: small components, simple logic, anything that isn't measurably slow. These hooks add complexity and have their own overhead — they're optimizations, not defaults.
If nothing is slow or broken, you likely don't need either.
Top comments (0)