Skip to main content

Command Palette

Search for a command to run...

useEffect in React.js [part-2]

Understanding the necessity of useEffect in React.js

Updated
โ€ข3 min read
useEffect in React.js [part-2]

What is need of useEffect ?

The need for useEffect in React is to handle side effects in functional components, allowing you to synchronize your component with an external system after rendering, preventing interference with the rendering process. It manages tasks like data fetching, setting up subscriptions (timers, event listeners), and directly manipulating the DOM, replacing class component lifecycle methods (like componentDidMount, componentDidUpdate) with a unified API.

What are Side Effects?
Side effects are any actions that reach outside the component's scope to interact with something React doesn't directly control, such as:

  • Data Fetching: Calling APIs to get data.

  • DOM Manipulation: Changing the document title or adding/removing elements.

  • Subscriptions: Setting up timers (setTimeout, setInterval) or event listeners (window resize, keypress).

  • Logging: Logging to the console.


What problem occurs when we do not use useEffect for side effects ?

Problem 1: Infinite Loops ๐Ÿ’ฅ

function BadComponent() {
  const [count, setCount] = useState(0);

  // โŒ This runs DURING render
  setCount(count + 1); // This triggers a re-render
                       // Which runs setCount again
                       // Which triggers another re-render
                       // INFINITE LOOP!

  return <div>{count}</div>;
}

What happens:

  • Render starts โ†’ setCount called โ†’ triggers re-render โ†’

  • New render starts โ†’ setCount called again โ†’ triggers re-render โ†’

  • CRASH! React stops after ~50 iterations to prevent browser freeze


Problem 2: Unpredictable Behavior

function BadAPICall() {
  const [data, setData] = useState(null);

  // โŒ API call during render
  fetch('/api/data')
    .then(res => res.json())
    .then(setData); // When data arrives, triggers re-render

  return <div>{data || 'Loading...'}</div>;
}

What happens:

  • Initial render โ†’ fetch called (Request #1 sent)

  • Parent re-renders for some reason โ†’ BadAPICall renders again โ†’ fetch called (Request #2 sent)

  • User clicks button โ†’ BadAPICall renders โ†’ fetch called (Request #3 sent)

  • Result: Dozens of unnecessary API calls! Your server gets hammered! ๐Ÿ“ก๐Ÿ’ฅ


Problem 3: Race Conditions

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

  // โŒ Fetch during render
  fetch(`/api/users/${userId}`)
    .then(res => res.json())
    .then(setUser);

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

// User changes from ID 1 โ†’ ID 5 quickly
// Request for user 1 sent (takes 500ms)
// Request for user 5 sent (takes 100ms)
// User 5 displays โœ“
// Then user 1 response arrives and overwrites it โŒ
// Wrong user shown!

React's Rendering Process

Here's what React actually does during a render:

// React's internal process (simplified)
function reactRenderProcess() {
  // Phase 1: RENDER (Pure calculation)
  const virtualDOM = YourComponent(); // Just calls your function

  // Phase 2: Compare with previous render
  const changes = compareVirtualDOMs(oldVirtualDOM, virtualDOM);

  // Phase 3: COMMIT (Actually update the browser)
  applyChangesToRealDOM(changes);

  // Phase 4: Run effects
  runAllUseEffects(); // โ† This is where side effects happen!
}

During Phase 1 (Render):

  • React might call your component multiple times

  • React might throw away the result without committing it

  • React needs to be able to pause and resume

  • This is why it must be pure!


Simple Analogy ๐ŸŽจ

Think of rendering like a painter planning a painting:

During Rendering (Planning Phase):

  • "I'll paint a tree here, a house there..."

  • Just thinking and sketching

  • Might change mind and start over

  • Don't order paint, don't call suppliers!

After Rendering (Execution Phase - useEffect):

  • Plan is finalized

  • Painting is on the wall

  • Now you can order more paint, call the client, post on social media

  • These are "side effects"

Summary: Why Not Update State During Rendering?

  1. Renders can happen multiple times - React might render but not commit

  2. Renders must be predictable - Same input = same output

  3. Prevents infinite loops - State updates during render cause re-renders

  4. Avoids duplicate side effects - API calls, subscriptions would run repeatedly

  5. Enables React features - Concurrent rendering, Suspense, time-slicing

The rule: Rendering = pure calculation. Side effects = useEffect.

Advanced useEffect Techniques in React