React useEffect on Mount

In the last lesson on the React useEffect Hook, you saw that useEffect runs after every render by default. This lesson shows how the empty dependency array makes a setup job run just once, when the component first appears.

🤔 Why run an effect only once?

A lot of setup work only makes sense to do one time, not on every render.

  • Say you load a user’s profile from a server when the page opens. You want to fetch it once, not again and again.
  • Say you start a timer when a screen appears. You want one timer, not a new one every render.
  • Say you read a saved theme from the browser’s storage. You read it once at the start, and you’re done.

So the pattern you’ll reach for the most is: do this setup task a single time, right when the component appears. React gives you a clean way to say that with useEffect.

📌 What does “mount” mean?

Before we go further, let’s get one word clear, because you’ll hear it all the time in React.

  • Mount means the first time a component is added to the screen.
  • A component mounts once. After that it can re-render many times, but it only mounts that first time.
  • Later, when it gets removed from the screen, we say it “unmounts”. But for now we only care about that first appearance.

So “run on mount” just means “run once, right after the component shows up for the first time”. Simple as that.

🧩 The empty dependency array

useEffect takes two things: a function to run, and a list of dependencies. That list is the second argument, and it controls when the effect runs.

This is the shape of an effect that runs once on mount. Notice the empty [] at the end.

useEffect(() => {
// setup code goes here, runs once after mount
}, []);

Let’s read what each part does.

  • The first argument is the function with your setup code inside it.
  • The second argument is the dependency array, the [] part. It’s a list of values React watches.
  • When that list is empty, there’s nothing to watch, so React runs the effect just once after the first render and never again.

So an empty array is your way of telling React, “run this one time on mount, then leave it alone”.

🔁 No array means every render

To see why [] matters, you have to see what happens when you leave it out. The behavior is very different.

  • If you pass an array, React runs the effect based on what’s in it.
  • If you pass an empty array [], the effect runs once on mount.
  • If you pass NO second argument at all, the effect runs after every single render.

That last case is the trap. Here’s the wrong way next to the right way, fetching some data.

// ❌ No dependency array - runs after EVERY render, fetches over and over
useEffect(() => {
fetch("/api/profile").then((res) => res.json()).then(setProfile);
});
// ✅ Empty array - runs ONCE on mount, fetches a single time
useEffect(() => {
fetch("/api/profile").then((res) => res.json()).then(setProfile);
}, []);

See the difference?

  • The top one has no [], so it fetches, sets state, that triggers a re-render, which fetches again. You get stuck in a loop.
  • The bottom one has [], so it fetches just once and stops.
  • That tiny [] is what saves you.

Don't forget the empty array

Leaving out the second argument is a common bug. Without it, an effect that fetches data or sets state can run on every render and keep going. If you mean “just once”, always add the empty [].

💡 A load-once-on-mount example

Let’s put it together in something that runs. A small component that loads a welcome message one time when it appears.

Read the effect first, then we’ll walk through it.

import { useState, useEffect } from "react";
function Welcome() {
const [message, setMessage] = useState("Loading...");
useEffect(() => {
// pretend this is data we fetched once on mount
setMessage("Welcome back, Riya!");
}, []);
return <p>{message}</p>;
}

Here’s what happens step by step.

  • The component mounts and renders first with message set to "Loading...".
  • Right after that, React runs the effect because it’s the first render.
  • The effect calls setMessage, which updates the state and re-renders the screen.
  • Now the screen shows the welcome text. The empty [] means the effect won’t run again.

Output

Loading...
Welcome back, Riya!

So the user sees “Loading…” for a flash, then the real message. And it loads only that one time, exactly what we wanted.

⚛️ StrictMode runs effects twice in dev

One thing that surprises people, so let’s clear it up now. In development you might notice your “once” effect runs twice.

  • React 18 has a tool called StrictMode that helps you catch bugs early.
  • In development only, it mounts your component, unmounts it, then mounts it again. So your effect runs two times.
  • This is on purpose. It checks that your setup and cleanup are written correctly.
  • It only happens in development. In the real production build, your mount effect runs once like normal.

So if you see two fetches or two logs while coding, don’t panic. That’s StrictMode doing its job, and your users will never see it.

This is dev-only behavior

The double-run from StrictMode is a development check, not a bug in your code. It does not happen in the production build. It’s nudging you to handle setup and cleanup properly.

🧩 What You’ve Learned

  • ✅ “Mount” means the first time a component is added to the screen, which happens once
  • useEffect(() => {...}, []) runs the effect a single time, right after mount
  • ✅ The empty [] is the dependency array, and an empty list means “run once and stop”
  • ✅ With no second argument, the effect runs after every render, which can cause repeated fetches or loops
  • ✅ Running once on mount is the most common use: loading initial data, starting a timer, or reading from storage
  • ✅ In development, React 18 StrictMode runs effects twice on purpose; production runs them once

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does useEffect(() => {...}, []) do?

    Why: An empty dependency array tells React there is nothing to watch, so the effect runs a single time after the first render (on mount).

  2. 2

    What happens if you leave out the second argument entirely?

    Why: With no dependency array, the effect runs after every single render. If it sets state, that can cause repeated runs or an endless loop.

  3. 3

    What does "mount" mean in React?

    Why: Mount is the first time a component appears on the screen. It happens once; after that the component can re-render many times.

  4. 4

    Why might your mount effect run twice during development?

    Why: In development, React 18 StrictMode runs effects twice on purpose to help you catch setup and cleanup bugs. It does not happen in the production build.

🚀 What’s Next?

Now you can run an effect once on mount with an empty array. Next you’ll learn what to put inside that array so an effect runs again only when specific values change.

React useEffect Dependencies

Share & Connect