React · Frontend system thinking
What is the difference between useMemo and useCallback?
Short answer
useMemo memoizes a computed value; useCallback memoizes a function reference. Both return the previous result until a dependency changes, and both are performance optimizations, not correctness guarantees.
React recreates values and functions on every render. useMemo lets you reuse the result of an expensive calculation when its inputs have not changed. useCallback is the function-specific version: it returns the same function identity until dependencies change.
function ProductList({ products, query }) {
const visible = useMemo(() => {
return products.filter((product) =>
product.name.toLowerCase().includes(query.toLowerCase()),
);
}, [products, query]);
const handleSelect = useCallback((id) => {
console.log("selected", id);
}, []);
return <List items={visible} onSelect={handleSelect} />;
}When they are useful
- A calculation is genuinely expensive and runs on many renders
- A stable function identity is required by
React.memoor an effect dependency - A value is passed to a memoized child or a dependency array
- A referential identity matters to a third-party API
Memoization has a cost: React stores the previous value and compares dependencies. Wrapping every value and callback can make code noisier without improving performance. Measure first, and remember that the React Compiler can automate some of this in projects that use it.
useMemo is not a semantic guarantee. React may discard memoized values in some circumstances, so never rely on it for correctness, such as ensuring a side effect runs only once.Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1What is the relationship between useCallback and React.memo?
- 2Does useMemo guarantee the calculation runs only once?
- 3Why can memoization make performance worse?
- 4How does the React Compiler change this advice?
Say it in the interview
useMemo caches a computed value, while useCallback caches a function reference. Both compare dependencies and reuse the previous result until something changes. I reach for them when a calculation is expensive or when stable identity matters to a memoized child or an effect. I do not wrap everything by default, because memoization has its own cost and is not a correctness guarantee.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live React mock interview and get scored feedback on depth, clarity and confidence.