← Back to React Course | Chapter 5: Core Hooks | Lesson 1 of 12

Introduction to useEffect

useEffect lets a component do something extra after it's drawn on screen, like sending a postcard right after you finish writing it.

What useEffect Is For

useEffect lets a component run code that isn't directly about calculating what to render, like fetching data or setting up a subscription. React runs this code after the component has rendered and the DOM has actually been updated.

Note: Think of useEffect as the place for anything that reaches outside of React itself -- timers, network requests, manual DOM changes.

Warning: Don't use useEffect for things that can be calculated directly during render -- that adds an unnecessary extra step.

Example: What useEffect Is For

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    function Logger() {
      const [count, setCount] = React.useState(0);
      React.useEffect(() => {
        console.log("Rendered! Count is", count);
      });
      return <button onClick={() => setCount(count + 1)}>{count}</button>;
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<Logger />);
  </script>
</body>
</html>

Basic useEffect Syntax

useEffect takes a function as its first argument, which React calls after rendering. Without a second argument, this function runs after every single render -- including the very first one.

Note: Always start simple: get the effect working with no dependency array, then add one once you understand when it should re-run.

Warning: An effect with no dependency array runs after EVERY render, which can be expensive or cause loops if it also updates state.

Example: Basic useEffect Syntax

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    function WindowSizeLogger() {
      React.useEffect(() => {
        console.log("Window width:", window.innerWidth);
      });
      return <p>Check the console after any state change.</p>;
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<WindowSizeLogger />);
  </script>
</body>
</html>

Effects Run After the DOM Updates

Unlike calculations done directly during render, effect code runs AFTER React has already updated the real DOM to match the latest render. This means an effect can safely read the current DOM, like measuring an element's size.

Note: If you need to read something from the actual rendered DOM (like an element's width), useEffect is the right place to do it.

Warning: Because effects run after painting, any state updates inside them trigger an additional, separate re-render.

Example: Effects Run After the DOM Updates

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    function MountMessage() {
      const [mounted, setMounted] = React.useState(false);
      React.useEffect(() => {
        setMounted(true);
      });
      return <p>{mounted ? "Mounted and effect ran!" : "Rendering..."}</p>;
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<MountMessage />);
  </script>
</body>
</html>
Common Mistakes
  1. Forgetting the dependency array entirely, causing the effect to run after every single render.
  2. Trying to make the effect function itself async directly, which isn't supported.
  3. Expecting useEffect to run before the browser paints the screen -- it runs after.
Chapter Summary
  • useEffect lets you run code in response to rendering, for things outside of React's rendering itself.
  • It runs after the component renders and the DOM has been updated.
  • Common uses include data fetching, subscriptions, and manually changing the DOM.
  • It takes a function and an optional array of dependencies.
Browser Support

Available since React 16.8, when Hooks were introduced.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.