useMemo vs useCallback vs React.memo

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

useMemo vs useCallback vs React.memo

In technical interviews, candidates are frequently asked to explain the differences between React’s three primary performance optimization tools: useMemo, useCallback, and React.memo.

While they all deal with caching (memoization) to prevent unnecessary work, they are used for completely different things.


1. React.memo (Memoizing a Component)

What it does: It is a Higher-Order Component (HOC). It wraps an entire React component and caches the rendered output.

By default, if a Parent component re-renders, React will force all of its Children to re-render, even if their props haven’t changed. If you wrap a Child in React.memo, you break this rule. React will only re-render the Child if its props have actually changed.

When to use it: Use it on components that are extremely heavy to render (like a massive data table or an complex interactive chart) and that frequently receive the exact same props from their parent.

// This component will ONLY re-render if 'data' changes.
// It will ignore parent renders otherwise.
const HeavyChart = React.memo(function HeavyChart({ data }) {
  return <ComplexSVGChart data={data} />;
});

2. useMemo (Memoizing a Value)

What it does: It is a hook. It caches the result of an expensive calculation inside a component.

During a standard re-render, React will re-execute every single line of code in your component function. If you have a complex mathematical calculation or a massive array sort, it will run again on every render. useMemo caches the result of that calculation and only re-runs it if its dependencies change.

When to use it: Use it when you are deriving data that takes a noticeable amount of CPU time to compute (e.g., sorting/filtering an array of 5,000 items).

function DataGrid({ users, sortOrder }) {
  // We ONLY run this massive sort if 'users' or 'sortOrder' changes.
  // If the component re-renders for some other reason, we reuse the cached result.
  const sortedUsers = useMemo(() => {
    return [...users].sort((a, b) => expensiveCompare(a, b, sortOrder));
  }, [users, sortOrder]);

  return <div>...</div>;
}

Note: You should also use useMemo if you are passing an object or array as a prop to a React.memo child component, to ensure the object reference remains stable across renders.


3. useCallback (Memoizing a Function)

What it does: It is a hook. It is almost identical to useMemo, but it is specifically designed to cache a function definition, rather than the result of calling a function.

Every time a component re-renders, it creates brand new function references in memory. const handleClick = () => {} creates a completely different function object on Render 1 vs Render 2.

When to use it: You almost exclusively use useCallback when you need to pass a callback function down as a prop to a Child component that is wrapped in React.memo.

function Parent() {
  const [count, setCount] = useState(0);

  // If we didn't use useCallback here, this function would be recreated 
  // on every render. Because the function reference would change, 
  // the <ExpensiveChild /> would see a "new" prop and be forced to re-render,
  // completely defeating the purpose of React.memo!
  const handleSubmit = useCallback(() => {
    api.submit();
  }, []);

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>Increment</button>
      <ExpensiveChild onSubmit={handleSubmit} />
    </div>
  );
}

const ExpensiveChild = React.memo(({ onSubmit }) => {
  /* ... */
});

Summary Table

ToolWhat does it cache?What is it applied to?
React.memoRendered UIA Component (e.g., function Button())
useMemoA calculated valueA variable (e.g., const sortedArr = ...)
useCallbackA function referenceA function (e.g., const handleClick = () => {})

Interview Questions

Q: Summarize exactly when to use React.memo, useMemo, and useCallback.
A:

  • React.memo: Wraps a component to prevent it from re-rendering if its props haven’t changed.
  • useMemo: Caches the result of an expensive mathematical calculation or array iteration.
  • useCallback: Caches a function definition so its memory reference doesn’t change when passed as a prop to a memoized child component.