React Curriculum

React.memo & Custom Comparator Functions

Medium100% Free~25 mins#react#react-memo#arepropsequal#performance#shallow-compare
Interview Answer (30-Second Summary)

React.memo is a higher-order component that skips re-rendering when props are shallowly equal (Object.is). You can pass a custom arePropsEqual(prevProps, nextProps) comparator, returning true to skip re-rendering or false to re-render.

Key Learning Objectives
✓

Understand how React.memo performs shallow prop comparison using Object.is.

✓

Implement a custom arePropsEqual comparator function to handle nested objects.

✓

Recognize why passing inline callbacks or object literals bypasses React.memo.

✓

Contrast arePropsEqual (return true to skip) with shouldComponentUpdate (return false to skip).

The Interview Problem & Context

What is logged to the console when comparing a standard React.memo component with inline props against a React.memo component with a custom arePropsEqual comparator?

1// Simulating React.memo comparison behavior
2function simulateReactMemo() {
3 const logs: string[] = [];
4
5 // 1. Standard shallow comparison with new inline object reference:
6 const obj1 = { id: 1 };
7 const obj2 = { id: 1 };
8 const isShallowEqual = Object.is(obj1, obj2); // false!
9 if (!isShallowEqual) {
10 logs.push('shallow-fail');
11 }
12
13 // 2. Custom arePropsEqual comparator checks data value:
14 function arePropsEqual(prev: { user: { id: number } }, next: { user: { id: number } }) {
15 return prev.user.id === next.user.id; // true -> skips render!
16 }
17 const isCustomEqual = arePropsEqual({ user: obj1 }, { user: obj2 });
18 if (isCustomEqual) {
19 logs.push('custom-pass');
20 }
21
22 const renderCount = 1; // Only 1 render because custom comparator skipped update!
23
24 return `${logs.join(' ')} ${renderCount}`;
25}
26
27console.log(simulateReactMemo());
Predict Console & Render Output
A

shallow-fail custom-pass 1

B

shallow-pass custom-pass 0

C

shallow-fail custom-fail 2

D

custom-pass shallow-fail 1

Execution Trace
Step 1 of 3 (Line 9)

Shallow comparison of new object references returns false, triggering render in standard React.memo.

Component / Call Stack
simulateReactMemo()
Hook State & Scope
isShallowEqual:false
Console Output(No console logs emitted)
Deep Architectural Explanation

React.memo and Custom Comparators

By default, React.memo(Component) performs a shallow comparison of all props using Object.is.

The Crucial Polarity Difference: arePropsEqual vs shouldComponentUpdate

This is a famous interview trap:

  • In Class components: shouldComponentUpdate(nextProps) returns true to RE-RENDER and false to skip.
  • In React.memo: arePropsEqual(prevProps, nextProps) returns true to SKIP RE-RENDER and false to re-render!
tsx
export const UserCard = React.memo(
  function UserCard({ user }: { user: User }) {
    return <div>{user.name}</div>;
  },
  (prevProps, nextProps) => {
    // Return TRUE if passing nextProps produces same result as prevProps (bails out)
    return prevProps.user.id === nextProps.user.id;
  }
);

When to Avoid React.memo

  1. Components that change on almost every render: The shallow prop comparison runs every time and still ends up rendering, adding net overhead.
  2. Components whose children change frequently: If props include non-memoized objects or callbacks, React.memo will always fail its check.
Common Interview Traps & Pitfalls
✕

Inverting the return value of arePropsEqual (returning false when props are equal).

✕

Wrapping every component in React.memo prematurely without measuring with the React Profiler.

✕

Performing deep recursive equality checks in arePropsEqual that take longer than rendering the component.

Senior Interviewer Follow-Up Probes
?

How does the React Compiler eliminate the need for manual React.memo wrappers?

?

Why doesn't React.memo prevent re-renders when internal useState or useContext changes?

?

How do you profile memoization bailout rates in Chrome DevTools?

Frequently Asked Interview Questions
What does React.memo do?

It is a higher-order component that memoizes the rendered output. If props are unchanged between renders, React skips rendering the component and reuses the last rendered result.

Return true if the component should NOT re-render (props are equal), and return false if the component SHOULD re-render (props changed).

No. If a component wrapped in React.memo updates its own internal useState or useReducer, it will still re-render.

Because a new object literal creates a new memory reference on every render, causing Object.is(prev, next) to evaluate to false.

React.memo is a higher-order component for memoizing entire component render trees based on props, while useMemo is a hook for memoizing individual values or functions inside a component.