Video thumbnail
3:45 / 15:30

Understanding the useEffect Hook

React Fundamentals & Hooks • Module 3 • Lesson 4

Notes
Transcript
Resources
Exercises
Discussion12

Understanding the useEffect Hook

The useEffect hook is one of the most important hooks in React. It allows you to perform side effects in your functional components. Think of side effects as anything that affects something outside of the current function being executed, such as:

  • Data fetching
  • Setting up subscriptions or event listeners
  • Manually changing the DOM
  • Logging

Basic Syntax

useEffect(() => {
  // Side effect code
  
  return () => {
    // Cleanup code (optional)
  };
}, [dependencies]);

The useEffect hook accepts two arguments:

  1. A function that contains the side effect code
  2. A dependency array (optional)

Dependency Array

The dependency array is a crucial part of useEffect. It determines when the effect should run:

  • No dependency array: Effect runs after every render
  • Empty dependency array []: Effect runs only once after the initial render
  • With dependencies [a, b]: Effect runs when any dependency changes

Example: Document Title

import { useState, useEffect } from 'react';

function PageTitle() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]); // Only re-run the effect if count changes
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

In this example, the document title will be updated whenever the count state changes.

Cleanup Function

The function returned from useEffect is called the cleanup function. It runs before the component unmounts and before the effect runs again (if it has dependencies that change).

useEffect(() => {
  const subscription = subscribeToData();
  
  // Cleanup function
  return () => {
    subscription.unsubscribe();
  };
}, []);

The cleanup function is important for preventing memory leaks by removing event listeners, canceling network requests, or cleaning up subscriptions.

Common Use Cases

1. Data Fetching

useEffect(() => {
  let isMounted = true;
  
  const fetchData = async () => {
    try {
      const response = await fetch('https://api.example.com/data');
      const data = await response.json();
      
      if (isMounted) {
        setData(data);
      }
    } catch (error) {
      if (isMounted) {
        setError(error);
      }
    } finally {
      if (isMounted) {
        setLoading(false);
      }
    }
  };
  
  fetchData();
  
  return () => {
    isMounted = false;
  };
}, []);

2. Event Listeners

useEffect(() => {
  const handleResize = () => {
    setWindowWidth(window.innerWidth);
  };
  
  window.addEventListener('resize', handleResize);
  
  return () => {
    window.removeEventListener('resize', handleResize);
  };
}, []);

Key Takeaways

  • useEffect allows you to perform side effects in functional components
  • The dependency array controls when the effect runs
  • Cleanup functions prevent memory leaks and unnecessary operations
  • Common use cases include data fetching, subscriptions, and DOM manipulation