Chapter 11: useEffect Hook

Once you truly understand useEffect, you’ll be able to handle almost any side effect in your app: fetching data, subscriptions, timers, DOM manipulations, and more.

We’ll go very slowly and clearly, like I’m sitting right next to you in Mumbai explaining it live with lots of examples you can copy-paste right now.

1. What is useEffect?

useEffect is a hook that lets you perform side effects in functional components.

Side effects = anything that reaches outside of React’s render flow:

  • Fetching data from an API
  • Setting up timers (setTimeout, setInterval)
  • Adding event listeners (window resize, scroll, etc.)
  • Manually changing the DOM
  • Subscribing to services (WebSockets, Firebase, etc.)

Syntax:

tsx

Key points:

  • useEffect runs after every render (by default)
  • You control when it runs using the dependency array
  • The cleanup function runs before the next effect and when the component unmounts

2. Fetching Data with useEffect (Most Common Use Case)

Let’s build a realistic user profile that fetches data from an API.

Create src/components/UserProfile.tsx

tsx

Important notes:

  • We use empty dependency array [] → effect runs only once when component mounts
  • We set loading and error states → great UX
  • Cleanup function is optional here (but good practice)

3. Dependencies Array – Controlling When Effect Runs

The dependency array tells React when to re-run the effect.

Dependency Array When does effect run?
[] (empty) Only once – on mount
No array at all Every render (almost never what you want – causes infinite loops!)
[someValue] On mount + whenever someValue changes
[userId] Whenever userId changes → perfect for fetching user by ID

Example: Fetch user when ID changes

tsx

4. Cleanup Functions – Preventing Memory Leaks

Cleanup is super important for:

  • Canceling timers
  • Removing event listeners
  • Aborting fetch requests
  • Closing WebSocket connections

Example: Timer that updates every second

tsx

Without cleanup → timer keeps running even after component unmounts → memory leak!

5. Common Patterns & Best Practices (2026)

  1. Fetch data on mount → useEffect(…, [])
  2. Fetch when prop/id changes → useEffect(…, [id])
  3. Run on every renderavoid (remove dependency array) → causes infinite loops
  4. Cleanup always when you set up something (timers, listeners, subscriptions)
  5. Avoid putting state setters in dependencies unless needed (causes unnecessary re-runs)

Summary – Chapter 11 Key Takeaways

  • useEffect = handle side effects (API calls, timers, listeners…)
  • Runs after render
  • Dependency array controls when it runs:
    • [] → once on mount
    • [dep] → on mount + when dep changes
    • no array → every render (dangerous!)
  • Cleanup function runs before next effect and on unmount
  • Always handle loading, error, and success states
  • Modern apps use React Query / SWR for data fetching (we’ll cover later)

Mini Homework

  1. Create a SearchUsers component
  2. Have an input field for user ID
  3. Use useEffect to fetch user when ID changes
  4. Show loading, error, and user data
  5. Bonus: Add a cleanup with AbortController to cancel fetch if user types fast

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *