R
Rishtaara
React: The Complete Guide
Lesson 17 of 28Article18 min

useEffect Hook

useEffect runs after React paints the screen. Use it for data fetching, timers, subscriptions, and syncing with non-React systems.

useEffect — side effects after render

useEffect runs after React paints the screen. Use it for data fetching, timers, subscriptions, and syncing with non-React systems.

Do not use useEffect for things you can compute during render — that belongs in plain JavaScript or useMemo.

Real-life example: useEffect is checking your mailbox after you finish cooking dinner — a separate task that happens after the main job (render) is done.

Fetch on mount
import { useState, useEffect } from "react";

function CourseList() {
  const [courses, setCourses] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    async function load() {
      try {
        const res = await fetch("/api/courses");
        const data = await res.json();
        if (!cancelled) setCourses(data);
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    load();
    return () => { cancelled = true; };
  }, []);

  if (loading) return <p>Loading...</p>;
  return <ul>{courses.map((c) => <li key={c.id}>{c.title}</li>)}</ul>;
}

Dependency array

[] runs once on mount. [userId] re-runs when userId changes. No array runs every render — rarely needed and often a bug.

Return a cleanup function to cancel timers, abort fetch, or remove listeners.

Real-life example: Dependencies are reminder alarms — [] means once on move-in day; [userId] means every time you change apartment roommate.

  • [] — fetch initial data, add one-time listeners
  • [dep] — refetch when dep changes
  • cleanup — return function from useEffect