🔴 HardWhat's Wrong?🐛 Debug Challenge

Infinite re-render in React useEffect

Buggy Code — Can you spot the issue?

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const options = { include: 'posts' }; // new object every render!

  useEffect(() => {
    fetchUser(userId, options).then(setUser);
  }, [userId, options]); // options changes every render!

  return <div>{user?.name}</div>;
}

Fixed Code

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  // Fix 1: Move constant outside component
  // const options = { include: 'posts' }; // outside component

  // Fix 2: useMemo to stabilize the reference
  const options = useMemo(() => ({ include: 'posts' }), []);

  // Fix 3: Just inline the values (often simplest)
  useEffect(() => {
    fetchUser(userId, { include: 'posts' }).then(setUser);
  }, [userId]); // stable deps only

  return <div>{user?.name}</div>;
}

Bug Explained

Bug: options is a new object on every render. useEffect sees a new options reference each time, triggers the effect, which sets state, which re-renders, which creates a new options... infinite loop.

Explanation: Objects/arrays created inside components get new references on each render. useEffect compares deps by reference. Inline the primitive values, use useMemo for objects, or move constants outside the component.

Key Insight: Objects in useEffect deps = infinite loops. useEffect uses Object.is (reference equality). Stabilize with useMemo or move outside component.

More What's Wrong? Debug Challenges

🟢 EasyAccidental global variable🟡 MediumWrong comparison with NaN🟡 MediumArray sort mutates original🟡 MediumSpread only shallow-copies nested arrays

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab