Technology

Actually Understanding useEffect

Beginner 12 min read VisTechie Team Technology
1 views

What useEffect is even for

useEffect runs code after React has already updated the DOM. It's the go-to spot for fetching data, setting up a subscription, or syncing with something outside React entirely - analytics, localStorage, that sort of thing.

The dependency array decides when it re-runs

  • Leave it out entirely → the effect runs after every single render
  • Pass an empty array [] → runs exactly once, right after the first render
  • List some values → it re-runs whenever any of those values change

Fetching data when the component mounts

import { useEffect, useState } from "react";

function ArticleList() {
  const [articles, setArticles] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch("/api/articles")
      .then((res) => res.json())
      .then((data) => setArticles(data))
      .finally(() => setLoading(false));
  }, []); // empty array = run once on mount

  if (loading) return <p>Loading...</p>;
  return <ul>{articles.map((a) => <li key={a._id}>{a.title}</li>)}</ul>;
}

Cleaning up after yourself

Return a function from the effect and React will call it right before the effect runs again, and again when the component unmounts. This is how you avoid leaking subscriptions or in-flight requests.

useEffect(() => {
  const controller = new AbortController();

  fetch("/api/articles", { signal: controller.signal })
    .then((res) => res.json())
    .then(setArticles)
    .catch(() => {}); // ignore abort errors

  return () => controller.abort(); // cleanup
}, []);

The mistake almost everyone makes

Forgetting to list a value inside the dependency array even though it's used inside the effect. ESLint's react-hooks/exhaustive-deps rule will catch this for you - leave it turned on, it's not being annoying, it's saving you a bug.

1 views

Comments

0/2000

Comments are reviewed before being published.

Loading comments...

Related Articles