Part 16: Mastering useEffect: Lifecycles, Dependencies & Cleanup

Part 16 Technology Updated September 12, 2026

Part 16: Mastering useEffect: Lifecycles, Dependencies & Cleanup

The useEffect hook lets you synchronize your component with external systems: fetching network data, reading/writing to browser APIs, setting timers, and subscribing to external event streams.


1. The Anatomy of useEffect

import { useEffect } from 'react';

useEffect(() => {
  // 1. Setup / Effect Code
  console.log('Effect executed');

  return () => {
    // 2. Optional Cleanup Function
    console.log('Cleanup executed');
  };
}, [/* 3. Dependency Array */]);

2. Understanding the Dependency Array

The second argument controls when the effect executes:

Case 1: No Dependency Array

Runs on every single render (mount + every state/prop update):

useEffect(() => {
  console.log('Component rendered or updated');
});

Case 2: Empty Dependency Array ([])

Runs once on initial mount, cleanup runs on unmount:

useEffect(() => {
  console.log('Component mounted to DOM');
  return () => console.log('Component unmounted');
}, []);

Case 3: Specific Dependencies ([userId, filter])

Runs on mount, and re-runs whenever any dependency changes value:

useEffect(() => {
  fetchUserData(userId);
}, [userId]);

3. The Cleanup Function

Whenever your effect establishes a continuous resource (subscription, timer, event listener), you must return a cleanup function to prevent memory leaks:

import { useState, useEffect } from 'react';

export default function WindowTracker() {
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWindowWidth(window.innerWidth);

    // Attach listener
    window.addEventListener('resize', handleResize);

    // Cleanup: Remove listener when component unmounts or before re-running
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return <p>Window width: {windowWidth}px</p>;
}

4. React 18 Strict Mode Double-Mounting

In React 18 development mode with React.StrictMode, React intentionally mounts, unmounts, and re-mounts every component to verify cleanup integrity. If your effect does not clean up properly, you will catch bugs early!


Key Takeaways

  • useEffect synchronizes components with external systems.
  • The dependency array dictates re-execution conditions.
  • Always provide cleanup functions for subscriptions, intervals, and event listeners.

In Part 17, we explore the useRef Hook for DOM access and mutable instance variables!