Interview Q&A / React

IntermediateIn-depth3 min readUpdated 2 Oct 2026

What is the difference between useMemo and useCallback, and when should you not use them?

SHORT ANSWER

useMemo caches the result of a calculation, and useCallback caches a function itself, both until their dependencies change. Use them for expensive calculations or to keep values stable for memoized children or effect dependencies; skip them for cheap work, where they only add complexity.

Explain it simply

Suppose your mess manager calculates the monthly bill for 500 students. If nothing changed since yesterday, recalculating the whole sheet is wasted effort. They keep yesterday's answer and redo it only when a student's meal count changes. That is memoization: remember a result and reuse it while the inputs are the same.

Every time a React component re-renders, its function body runs again. Every calculation is repeated and every function defined inside it is created again as a new object.

  • useMemo(() => compute(), [deps]) remembers the result of compute.
  • useCallback(fn, [deps]) remembers the function fn itself, so you get the same function object on each render.

In fact, useCallback(fn, deps) is the same as useMemo(() => fn, deps).

Example

jsx
const StudentRow = memo(function StudentRow({ student, onSelect }) {
  return <li onClick={() => onSelect(student.id)}>{student.name}</li>;
});

function StudentList({ students, query }) {
  const [selectedId, setSelectedId] = useState(null);

  // useMemo: avoid re-filtering thousands of students on unrelated re-renders
  const visible = useMemo(
    () => students.filter((s) => s.name.toLowerCase().includes(query.toLowerCase())),
    [students, query]
  );

  // useCallback: keep the same function so memo(StudentRow) can skip re-rendering
  const handleSelect = useCallback((id) => setSelectedId(id), []);

  return (
    <ul>
      {visible.map((s) => (
        <StudentRow key={s.id} student={s} onSelect={handleSelect} />
      ))}
    </ul>
  );
}

When selectedId changes, the filtered list is reused, and each StudentRow gets the same onSelect function as before, so memo lets unchanged rows skip rendering.

How it works

React stores the cached value along with the dependency array. On the next render it compares each dependency with the previous one using Object.is. If all are the same, it returns the cached value. If any changed, it runs the function again and stores the new result.

useCallback only helps if something cares that the function is the same object: a child wrapped in memo, or a hook that lists the function in its dependency array. On its own, a stable function does not make anything faster.

When not to use them

  • Cheap calculations. Adding two numbers or mapping a short array costs less than the memoization bookkeeping.
  • Functions passed to plain DOM elements or to children that are not memoized. The child re-renders anyway.
  • To fix bugs. If your code only works with useMemo, there is a logic problem. React may discard cached values, so code must stay correct without them.
  • If your project uses the React Compiler. It adds this kind of memoization automatically at build time, so manual useMemo and useCallback are needed much less.

Measure with the React DevTools Profiler before adding them.

Real-world use

  • Filtering or sorting a large table when the user types in an unrelated field.
  • Passing callbacks to a long list of memo rows.
  • Keeping an object or function stable when it is a dependency of useEffect, so the effect does not run on every render.

Common mistakes

  • Wrapping everything "just in case", which makes code harder to read for no gain.
  • Missing dependencies, which returns stale values. Keep the dependency array honest.
  • Using useCallback without memo on the child, then wondering why nothing improved.
  • Creating a new object or array in the dependency list, like [{ id }], which changes every render and defeats the cache.

What to say in the interview

"useMemo caches the result of a calculation and useCallback caches a function reference, both recomputed only when their dependencies change. useCallback is really useMemo returning a function. I use useMemo for genuinely expensive calculations, and both hooks when I need a stable reference for a memo-wrapped child or an effect dependency. I don't use them for cheap work, and I profile first. With the React Compiler, most of this manual memoization is handled automatically."

Follow-up questions

  • How does React.memo relate to useCallback?
  • Why should code still work correctly if useMemo recalculates?
  • What does the React Compiler do?

#hooks#performance#memoization#usememo#usecallback

Related questions

Practise more React questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open React quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.