Rreact.wiki
React Interview Questions

How does React.memo work, and what are its limitations with props containing objects or functions?

PerformanceMedium6/21/2026memoizationshallow-comparisonperformancepropsoptimization

`React.memo` prevents re-renders by performing a shallow comparison of props, but it fails to detect changes in mutated objects or newly created inline functions/objects — leading to stale renders or missed optimizations.

Short Answer

React.memo wraps a component and skips re-rendering if its props pass a shallow equality check (Object.is) between renders — but it cannot detect deep changes in objects/arrays, nor does it treat equivalent inline functions or objects as equal across renders, often causing unexpected re-renders or missed optimizations.

Details

React.memo is a higher-order component that implements memoization at the component level. On each render, it compares the current and previous props using a shallow comparison: for primitives, it checks value equality; for objects/arrays/functions, it checks reference equality. If all props are Object.is-equal, React reuses the last rendered output (bailing out). Crucially, this means:

  • { count: 5 } !== { count: 5 } (different references → re-render)
  • () => {} !== () => {} (new function every render → re-render)
  • Mutating an object prop (e.g., obj.x = 42) preserves the reference → React.memo sees “no change” but renders stale UI.
    The default comparison can be overridden with a custom arePropsEqual function — but doing so correctly requires careful deep comparison or selective key-based checks (and carries perf overhead).

Example

TSX
const UserProfile = React.memo(({ user, onEdit }: { user: User; onEdit: () => void }) => (
  <div>
    <h2>{user.name}</h2>
    <button onClick={onEdit}>Edit</button>
  </div>
));
 
// ❌ Problematic usage:
function Parent() {
  const [count, setCount] = useState(0);
  return (
    <UserProfile 
      user={{ id: 1, name: 'Alex' }} // new object every render
      onEdit={() => setCount(c => c + 1)} // new function every render
    />
  );
}
// → UserProfile re-renders every time, despite logical equivalence.

Bonus

To stand out: explain when not to use React.memo (e.g., cheap components, or when profiling shows no benefit), mention that hooks like useCallback and useMemo are often needed alongside React.memo to stabilize function/object props, and note that React.memo only affects parent-triggered re-renders — it won’t prevent re-renders caused by local state or context changes within the memoized component. Bonus points for referencing the official React docs’ warning: “Don’t rely on memo as a semantic guarantee — it’s a performance hint.”

How does React.memo work, and what are its limitations with props containing objects or functions? — react.wiki