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>;
}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: 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.