React - useEffect: Side Effects

This is what allows you to execute code when your component mounts, updates, or unmounts. API calls, timers, subscriptions... it all happens here!


Understanding useEffect

What is a "Side Effect"?

A side effect is any action that falls outside the scope of pure rendering:

  • API calls: fetching data
  • Timers: setTimeout, setInterval
  • 🔌 Subscriptions: websockets, event listeners
  • 💾 localStorage: saving data
  • Analytics: event tracking
  • DOM manipulation: focus, scroll

Simplified Lifecycle

import { useState, useEffect } from 'react'

function LifecycleWithUseEffect() {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('')

  // 🎬 Equivalent componentDidMount + componentDidUpdate
  useEffect(() => {
    console.log('Component mounted OR updated')
    document.title = `Count: ${count}`
  }) // ← No array = on every render!

  // 🎬 Equivalent componentDidMount only
  useEffect(() => {
    console.log('🎬 Component mounted (ONLY ONCE)')
    
    // 💀 Cleanup = componentWillUnmount
    return () => {
      console.log('💀 Cleanup before unmounting')
    }
  }, []) // ← Empty array = only once!

  // 🎯 Effect specific to count
  useEffect(() => {
    console.log('📊 Count changed:', count)
    
    if (count > 10) {
      alert('Count exceeds 10!')
    }
  }, [count]) // ← Triggers when count changes!

  // 👤 Effect specific to name
  useEffect(() => {
    console.log('👤 Name changed:', name)
    
    if (name.length > 0) {
      localStorage.setItem('userName', name)
    }
  }, [name]) // ← Triggers when name changes!

  return (
    <div>
      <h3>Count: {count}</h3>
      <button onClick={() => setCount(count + 1)}>+1</button>

      <input
        value={name}
        onChange={e => setName(e.target.value)}
        placeholder="Your name..."
      />
    </div>
  )
}

Resources For Further Learning