useEffect
โš›๏ธ React 18+ ๐ŸŸข Chapter 19 of 39 ๐Ÿ“‚ Phase 08: Lifecycle and Effects ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Effect Definition ยท External Systems ยท Empty vs Full Dependency Array ยท Cleanup Function ยท Timer Example ยท Browser Events ยท API Requests
useEffect lets a component synchronize with something outside React's own rendering โ€” a timer, a browser event, a network request. This chapter covers exactly when and how to use it, and just as importantly, when not to.
1What Counts as an External System

React components render based on props and state โ€” but real apps also need to interact with things React doesn't manage directly: setInterval timers, browser APIs like window.addEventListener, or a network request to a server. useEffect is the tool for connecting a component to these external systems.

2Dependency Arrays: Controlling When an Effect Runs
๐Ÿ’ป Example 1: A Live Clock with Cleanup
import { useEffect, useState } from "react";

function Clock() {
  const [time, setTime] = useState(new Date());

  useEffect(() => {
    const timer = setInterval(() => {
      setTime(new Date());
    }, 1000);

    return () => clearInterval(timer);   // cleanup function
  }, []);   // empty array - run once on mount

  return <p>{time.toLocaleTimeString()}</p>;
}
๐Ÿ” The Three Dependency Array Patterns:
  • No array at all: runs after every single render (rarely what you want)
  • [] empty array: runs exactly once, when the component first mounts
  • [someValue]: runs once on mount, then again any time someValue changes
3The Cleanup Function

Returning a function from inside useEffect tells React to run it right before the effect runs again, or when the component unmounts entirely. In the clock example above, clearInterval(timer) stops the old timer before starting a fresh one โ€” without this cleanup, you'd accumulate multiple overlapping timers every time the effect re-ran, a very common source of subtle bugs and memory leaks.

โš ๏ธ Missing a Dependency in the Dependency Array

If an effect uses a variable from component scope (like a prop or state value) but that variable isn't listed in the dependency array, the effect can run with a stale, outdated value โ€” a bug that's notoriously hard to track down. React's ESLint plugin will warn about this; when in doubt, include every value the effect actually reads.

๐Ÿ’ป Hands-on Interactive Practice Challenge

Build a component that subscribes to the browser's online/offline status using window event listeners inside useEffect, with proper cleanup.

React Practice Challenge โ–ถ Run in Compiler
import { useState, useEffect } from "react";

function NetworkStatus() {
  const [isOnline, setIsOnline] = useState(navigator.onLine);

  useEffect(() => {
    function goOnline() { setIsOnline(true); }
    function goOffline() { setIsOnline(false); }

    window.addEventListener("online", goOnline);
    window.addEventListener("offline", goOffline);

    return () => {
      window.removeEventListener("online", goOnline);
      window.removeEventListener("offline", goOffline);
    };
  }, []);

  return <p>{isOnline ? "๐ŸŸข Online" : "๐Ÿ”ด Offline"}</p>;
}
Run This Challenge in Online JS IDE โ†’
โ“ Frequently Asked Questions (FAQ)

Q Do I need useEffect for every side effect?

No โ€” useEffect is specifically for synchronizing with something outside React (timers, subscriptions, network requests). Simple event handlers, like a button's onClick, don't need useEffect at all.

Q Why does my effect run twice in development mode?

In React 18's StrictMode (used by default in new Vite projects), effects intentionally run twice in development only, to help you catch missing cleanup functions. This doesn't happen in production builds.

OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on React 18+ ยท Last updated August 2026