Back
LearnReact — Build Modern Web AppsuseEffect — running side effects

useEffect — running side effects

2 min read

Some work happens "outside" rendering

A component's main job is to return JSX from its props and state. But sometimes you need to do something extra — fetch data, set a timer, save to localStorage, or update the page title. These are called side effects, and React handles them with useEffect.

The basic shape

import { useState, useEffect } from "react";

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setSeconds((s) => s + 1);
    }, 1000);

    return () => clearInterval(id);  // cleanup
  }, []);

  return <p>{seconds} seconds passed</p>;
}

useEffect takes a function to run after the component renders.

The dependency array — the key to control

That [] at the end is the dependency array, and it controls when the effect runs:

  • [] (empty) → run once, when the component first appears. (Perfect for loading data.)
  • [count] → run again whenever count changes.
  • no array → run after every render (rarely what you want).
useEffect(() => {
  console.log("count changed to", count);
}, [count]);

Cleanup — tidy up after yourself

If your effect starts something ongoing (a timer, a subscription), return a function to stop it. React runs that cleanup when the component disappears. In the Timer above, return () => clearInterval(id) stops the timer so it does not leak.

Why does useEffect matter?

Because it is how React talks to the outside world — APIs, timers, the browser. The single most common use is loading data when a page opens, which we do next.

useEffect runs side effects after render. The dependency array controls when: [] = once, [x] = when x changes. Return a cleanup function for timers and subscriptions.

Tip