← React tutorial

React

Side Effects with useEffect

useEffect runs code after a component renders — fetching data, subscribing to something, or manually touching the DOM.

Example: a live-updating clock

import { useState, useEffect } from "react";

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

  useEffect(() => {
    const id = setInterval(() => setTime(new Date().toLocaleTimeString()), 1000);
    return () => clearInterval(id);
  }, []);

  return <p>Current time: {time}</p>;
}

The second argument, [] — an empty dependency array — tells React "only run this effect once, right after the very first render," rather than after every single re-render. Change it to [time] and the effect would instead re-run every time time changes — usually not what you'd want here, since it would reset the interval constantly instead of letting it tick steadily.

Why the function returned inside useEffect matters

The function returned from the effect (() => clearInterval(id)) is cleanup — React calls it automatically if the component is removed from the page, stopping the interval so it doesn't keep silently running (and wasting resources) after the clock is no longer even visible. Forgetting cleanup for things like intervals, timers, and subscriptions is a very common source of subtle bugs in real React apps.

Example
import { useState, useEffect } from "react";

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

  useEffect(() => {
    const id = setInterval(() => setTime(new Date().toLocaleTimeString()), 1000);
    return () => clearInterval(id);
  }, []);

  return <p>Current time: {time}</p>;
}
Output
Renders the current time as text, updating once per second.