React useEffect Dependency Pitfall


import { useEffect, useState } from "react";
 
export default function App() {
  const [count, setCount] = useState(0);
  const params = { when: 69 }; // new object each render
  // Fix with `useMemo`
  // const params = useMemo(() => ({ when: 69 }), []);
 
  useEffect(() => {
    console.log("Effect ran!");
  }, [params]); // runs every render, even if contents are same
 
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Clicked {count} times
    </button>
  );
}
 
  • In React, useEffect(..., [deps]) runs when dependencies change by reference, not by content
  • In JavaScript, writing { when: 69 } creates a new object every render, so React thinks it’s different each time β†’ effect re-runs unnecessarily β†’ causes extra or infinite re-fetching
  • βœ… Fix: Use useMemo (or useCallback) when you need a stable object/function for dependencies
  • ⚠️ Don’t overuse useMemo β€” only apply it when object identity matters (like dependencies, props for memoized children)

Tip

Objects/arrays/functions recreate each render β†’ useMemo/useCallback helps keep them stable only when necessary.

References