HardPerformance🐛 Debug Challenge

Every parent render creates new array prop — child never skips

Buggy Code — Can you spot the issue?

function shallowEqual(a, b) {
  return Object.keys(a).every(k => a[k] === b[k]);
}

let childRenders = 0;
function Child({ items }) { childRenders++; return items.length; }
function MemoChild(props) {
  if (MemoChild._prev && shallowEqual(MemoChild._prev, props)) return 'skip';
  MemoChild._prev = props;
  return Child(props);
}

// Bug: inline array literal — new reference on every "render"
const RENDER_COUNT = 4;
for (let i = 0; i < RENDER_COUNT; i++) {
  MemoChild({ items: [1, 2, 3] }); // new [1,2,3] every render!
}

console.log(childRenders); // should be 1, is 4

Fixed Code

function shallowEqual(a, b) {
  return Object.keys(a).every(k => a[k] === b[k]);
}

let childRenders = 0;
function Child({ items }) { childRenders++; return items.length; }
function MemoChild(props) {
  if (MemoChild._prev && shallowEqual(MemoChild._prev, props)) return 'skip';
  MemoChild._prev = props;
  return Child(props);
}

// Fix: stable reference — useMemo in real React
const stableItems = [1, 2, 3]; // defined once outside render (or in useMemo)

const RENDER_COUNT = 4;
for (let i = 0; i < RENDER_COUNT; i++) {
  MemoChild({ items: stableItems }); // same reference every time
}

console.log(childRenders);

Bug Explained

Bug: [1, 2, 3] creates a new array reference on every render. shallowEqual sees items changed (old array !== new array) even though contents are identical.

Explanation: stableItems is created once. Every render passes the same reference — shallowEqual sees no change after the first render.

Key Insight: For stable array/object props to React.memo children, use useMemo: const items = useMemo(() => [1, 2, 3], []). Or lift the constant outside the component entirely.

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab