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:

JSX
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:

JSX
const result = useMemo(() => {
  return expensiveCalculation();
}, []);

React stores the computed value.

Syntax#

JSX
const value = useMemo(() => {
  return computation;
}, [dependencies]);

Example#

Without useMemo:

JSX
const sortedUsers = users.sort();

Runs:

Every Render

With useMemo:

JSX
const sortedUsers = useMemo(() => {
  return users.sort();
}, [users]);

Runs only when:

JAVASCRIPT
users;

changes.

4. Callback Memoization: useCallback#

useCallback memoizes:

Functions

between renders.

Example:

JSX
const handleClick = useCallback(() => {
  saveUser();
}, []);

React returns the same function reference until dependencies change.

Syntax#

JSX
const callback = useCallback(() => {}, [dependencies]);

5. Under the Hood: Function References in JS#

Consider:

JSX
function App() {
  const handleClick = () => {
    console.log("Click");
  };

  return <Child onClick={handleClick} />;
}

Every render creates:

New Function

Visual Representation#

Render #1

JAVASCRIPT
handleClick = fn1;

Render #2

JAVASCRIPT
handleClick = fn2;

Render #3

JAVASCRIPT
handleClick = fn3;

Different references.

Why Is This a Problem?#

Consider:

JSX
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#

JSX
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:

JSX
const filteredUsers = useMemo(() => {
  return users.filter((user) => user.active);
}, [users]);

useCallback#

Memoizes:

Functions

Example:

JSX
const handleSubmit = useCallback(() => {
  saveUser();
}, []);

Internal Relationship#

A common interview question.

Internally:

JAVASCRIPT
useCallback(fn, deps);

is conceptually similar to:

JAVASCRIPT
useMemo(() => fn, deps);

Both rely on memoization.

7. Real-World Sizing & Calculations#

Bad:

JSX
const expensiveResult = calculateRevenue(products);

Runs every render.

Better:

JSX
const expensiveResult = useMemo(() => {
  return calculateRevenue(products);
}, [products]);

Real World Example: useCallback#

Bad:

JSX
<SaveButton onSave={() => saveUser()} />

Creates a new function every render.

Better:

JSX
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:

JSX
const title = useMemo(() => "FrontendPrep", []);

No expensive calculation exists.

Optimization is unnecessary.

8. Common Interview Q&A#

Should useCallback Be Used Everywhere?

Answer:

No

Example:

JSX
const handleClick = useCallback(() => {
  console.log("Hi");
}, []);

If:

JAVASCRIPT
handleClick;

is not passed to memoized children:

No Benefit

useMemo and React.memo#

A common interview topic.

Example:

JSX
const users = useMemo(() => {
  return fetchUsers();
}, []);

Passed to:

JSX
<UsersList users={users} />

Stable values help:

JSX
React.memo();

avoid re-renders.

useCallback and React.memo#

Example:

JSX
const handleClick = useCallback(() => {
  saveUser();
}, []);

Passed to:

JSX
<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:

JSX
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.

JAVASCRIPT
useCallback(fn, deps);

is similar to:

JAVASCRIPT
useMemo(() => fn, deps);

useMemo vs useCallback Summary#

FeatureuseMemouseCallback
MemoizesValuesFunctions
ReturnsComputed ResultFunction Reference
PurposeAvoid RecalculationAvoid Function Recreation
Common Use CasesSorting, Filtering, Expensive ComputationsEvent 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.