One of the most common React performance interview questions is:
What is the difference between useMemo and useCallback?
Most developers answer:
useMemo memoizes values.
useCallback memoizes functions.
While correct, interviewers often go deeper:
- Why do we need memoization?
- How do useMemo and useCallback work internally?
- When should they be used?
- Can they hurt performance?
- How do they interact with React.memo?
- What problems do they solve?
Let's understand them from first principles.
1. Why Do We Need Memoization?#
React components re-render whenever:
- State changes
- Props change
- Context changes
- Parent components re-render
Example:
function App() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Every update causes:
Render
↓
Execute Component
↓
Recreate Variables
Functions
Objects
Sometimes this creates unnecessary work.
2. What is Memoization?#
Memoization is an optimization technique that stores a previously computed result and reuses it when inputs remain unchanged.
Instead of:
Recompute Every Time
we can:
Reuse Previous Result
Visual Representation#
Without Memoization:
Render
↓
Calculate
↓
Render
↓
Calculate
↓
Render
↓
Calculate
With Memoization:
Render
↓
Calculate
↓
Store Result
↓
Reuse Result
↓
Reuse Result
3. Value Memoization: useMemo#
useMemo memoizes:
Values
between renders.
Example:
const result = useMemo(() => {
return expensiveCalculation();
}, []);
React stores the computed value.
Syntax#
const value = useMemo(() => {
return computation;
}, [dependencies]);
Example#
Without useMemo:
const sortedUsers = users.sort();
Runs:
Every Render
With useMemo:
const sortedUsers = useMemo(() => {
return users.sort();
}, [users]);
Runs only when:
users;
changes.
4. Callback Memoization: useCallback#
useCallback memoizes:
Functions
between renders.
Example:
const handleClick = useCallback(() => {
saveUser();
}, []);
React returns the same function reference until dependencies change.
Syntax#
const callback = useCallback(() => {}, [dependencies]);
5. Under the Hood: Function References in JS#
Consider:
function App() {
const handleClick = () => {
console.log("Click");
};
return <Child onClick={handleClick} />;
}
Every render creates:
New Function
Visual Representation#
Render #1
handleClick = fn1;
Render #2
handleClick = fn2;
Render #3
handleClick = fn3;
Different references.
Why Is This a Problem?#
Consider:
const Child = React.memo(({ onClick }) => {
return <button>Click</button>;
});
Even though:
UI Hasn't Changed
React sees:
New Function Reference
and re-renders the child.
Solution Using useCallback#
const handleClick = useCallback(() => {
console.log("Click");
}, []);
Now:
Same Function Reference
between renders.
Visual Representation#
Without useCallback:
Render
↓
New Function
↓
Child Re-renders
With useCallback:
Render
↓
Same Function
↓
Child Skips Render
when used with React.memo.
6. useMemo vs. useCallback: The Core Differences#
useMemo#
Memoizes:
Values
Example:
const filteredUsers = useMemo(() => {
return users.filter((user) => user.active);
}, [users]);
useCallback#
Memoizes:
Functions
Example:
const handleSubmit = useCallback(() => {
saveUser();
}, []);
Internal Relationship#
A common interview question.
Internally:
useCallback(fn, deps);
is conceptually similar to:
useMemo(() => fn, deps);
Both rely on memoization.
7. Real-World Sizing & Calculations#
Bad:
const expensiveResult = calculateRevenue(products);
Runs every render.
Better:
const expensiveResult = useMemo(() => {
return calculateRevenue(products);
}, [products]);
Real World Example: useCallback#
Bad:
<SaveButton onSave={() => saveUser()} />
Creates a new function every render.
Better:
const handleSave = useCallback(() => {
saveUser();
}, []);
<SaveButton onSave={handleSave} />;
8. Common Interview Q&A#
Should useMemo Be Used Everywhere?
Answer:
No
Memoization itself has a cost.
React must:
Store Value
Compare Dependencies
Manage Cache
Example#
Bad:
const title = useMemo(() => "FrontendPrep", []);
No expensive calculation exists.
Optimization is unnecessary.
8. Common Interview Q&A#
Should useCallback Be Used Everywhere?
Answer:
No
Example:
const handleClick = useCallback(() => {
console.log("Hi");
}, []);
If:
handleClick;
is not passed to memoized children:
No Benefit
useMemo and React.memo#
A common interview topic.
Example:
const users = useMemo(() => {
return fetchUsers();
}, []);
Passed to:
<UsersList users={users} />
Stable values help:
React.memo();
avoid re-renders.
useCallback and React.memo#
Example:
const handleClick = useCallback(() => {
saveUser();
}, []);
Passed to:
<SaveButton onClick={handleClick} />
Stable functions help memoized components skip renders.
Common Interview Questions#
What Does useMemo Do?#
Memoizes computed values between renders.
What Does useCallback Do?#
Memoizes function references between renders.
What Problem Does useMemo Solve?#
Avoids expensive recalculations.
What Problem Does useCallback Solve?#
Avoids unnecessary function recreation.
Does useCallback Prevent Re-renders?#
Not by itself.
It helps:
React.memo();
work effectively.
Does useMemo Improve Every Application?#
No.
Use it only when actual performance benefits exist.
Is useCallback Built Using useMemo?#
Conceptually yes.
useCallback(fn, deps);
is similar to:
useMemo(() => fn, deps);
useMemo vs useCallback Summary#
| Feature | useMemo | useCallback |
|---|---|---|
| Memoizes | Values | Functions |
| Returns | Computed Result | Function Reference |
| Purpose | Avoid Recalculation | Avoid Function Recreation |
| Common Use Cases | Sorting, Filtering, Expensive Computations | Event Handlers, Callback Props |
| Works With React.memo | ✅ Yes | ✅ Yes |
Senior-Level Interview Answer#
useMemo and useCallback are React Hooks used for memoization and performance optimization. useMemo memoizes computed values and recomputes them only when dependencies change, making it useful for expensive calculations and derived data. useCallback memoizes function references and returns the same function instance between renders unless dependencies change. This is particularly useful when passing callbacks to memoized child components using React.memo. Both hooks help reduce unnecessary work, but they should only be used when profiling indicates a real performance benefit because memoization itself introduces overhead.
Common Interview Mistakes#
❌ useMemo and useCallback Prevent Re-renders#
Correct:
They reduce unnecessary work.
They do not prevent renders
by themselves.
❌ useMemo Should Be Used Everywhere#
Correct:
Memoization has a cost.
❌ useCallback Makes Functions Faster#
Correct:
It stabilizes references.
It does not speed up execution.
❌ React.memo Alone Solves Performance Problems#
Correct:
Stable props and callbacks
are often required.
Key Takeaways#
- Memoization: Caching the results of expensive operations to skip redundant recalculations on renders.
- useMemo: Memoizes the returned value of a function calculation.
- useCallback: Memoizes the function instance reference itself.
- Referential Identity: Critical for passing stable callbacks to child components optimized with
React.memo. - Optimization Cost: Do not memoize trivially cheap values, as hooks introduce overhead.