React Interview Question: useMemo vs useCallback vs React.memo
Short answer: useMemo caches a computed value, useCallback caches a function, and React.memo skips re-rendering a component when its props haven't changed.
const visible = useMemo(() => products.filter((p) => p.inStock), [products]); // value
const onSelect = useCallback((id) => setSelected(id), []); // function
const ProductRow = React.memo(function ProductRow({ product, onSelect }) { ... }); // component
How they work together
React.memo compares props with Object.is. A new function or array created on every parent render is a new reference, so memo always sees "changed" props. useCallback and useMemo keep those references stable so memo can actually skip work.
function ProductList({ products }) {
const [selected, setSelected] = useState(null);
const onSelect = useCallback((id) => setSelected(id), []); // stable reference
return products.map((p) => <ProductRow key={p.id} product={p} onSelect={onSelect} />);
}
When they're worth it
- An expensive calculation (sorting or filtering thousands of items) on each render.
- Props passed to a memoised child that's expensive to render.
- Values used as effect dependencies that must stay stable.
When they're not
- Cheap calculations: memoisation has its own cost.
- Children that aren't wrapped in
memo: a stable callback alone changes nothing.
Bonus: React Compiler
React Compiler adds this memoisation automatically at build time, so in projects that use it, manual useMemo/useCallback/memo is rarely needed. Interviewers like hearing that you'd measure with the React Profiler before optimising.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.