Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 4

Understanding `useEffect`: Purpose and Concepts

Recommended resources

Hello! Welcome to the final lesson in our "Modern React Fundamentals" module.

In our last few lessons, you've done a fantastic job learning how to build components with props and manage their internal state with useState. You now know how to create interactive UIs that respond to user input, like the controlled forms we built.

However, React components often need to do more than just render UI. They need to interact with the "outside world"—fetch data from a server, set timers, or subscribe to real-time events. These actions are called side effects.

Today, our goal is to explain the purpose of side-effect management and the useEffect hook. This is a conceptual lesson; we won't be writing any code, but we'll build the mental model you need to use effects correctly. Understanding this is the final piece of the React puzzle before we can start building full-stack applications with Next.js.


1. What is a Side Effect?

In React, a component's main job is to take its current props and state and return a description of the UI. Ideally, this process is "pure": for the same inputs (props and state), it should always produce the same output (JSX).

A side effect is any action that affects something outside the scope of the component's rendering logic. Think of it as your component interacting with the world beyond its own borders.

Given your interest in nature, let's use a fun analogy.

Mastering React's useEffect with a Gardening Analogy

This short post on LinkedIn uses a wonderful gardening analogy to explain useEffect. It's a great way to build an intuitive understanding of a tricky concept.

Read the first half of the post, up to the section 'What Are Side Effects?'. This will introduce the core metaphor of your component as a gardener whose job is to plant the UI.

As the article explains, if the gardener's only job is to arrange the garden (the UI), then tasks like "buying seeds" or "turning on the sprinklers" are side effects. They are essential for the garden's health but aren't part of the direct act of planting.

To see some more technical examples, watch this short clip.

#42 Understanding side effects in React | Side effect, Reducer and Context | A Complete React Course

This video from procademy provides a clear, technical definition of side effects in React.

Watch from 00:32 to 01:44. The presenter gives common examples like making HTTP requests, using browser storage, and setting timers.

Common side effects include:

  • Fetching data from an API (e.g., getting user data).
  • Setting up timers or intervals (setTimeout, setInterval).
  • Manually changing the DOM (e.g., updating document.title).
  • Subscribing to real-time data sources (like a chat service).
  • Reading from or writing to browser storage (localStorage).

The key problem is: if you put a side effect directly inside your component function, it will run every single time the component renders. This can lead to chaos, like firing off an API request every time a user types a single character in a form. We need a way to control when these effects happen.



2. useEffect: The Gardener's To-Do List

This is where the useEffect hook comes in. It's a special function that gives you a safe place to run your side effects after React has finished rendering the UI.

React useEffect Hook Visual Metaphor
A visual pun on React "hooks." The `useEffect` hook lets us "hook into" the component's lifecycle to perform actions after rendering.

Think of useEffect as the gardener's to-do list. The gardener first plants the garden (renders the UI), and then checks the list to see if any other tasks need to be done.

The useEffect hook has two main parts:

  1. An effect function: The code you want to run (e.g., fetch data).
  2. A dependency array: A list that tells React when to re-run the effect function.

The dependency array is the "trigger" for your to-do list item. It's the puzzle piece that gives you precise control.

Let's see how this works in practice.

#42 Understanding side effects in React | Side effect, Reducer and Context | A Complete React Course

This next clip from the same video demonstrates how the dependency array controls the execution of the effect.

Watch from 06:49 to 11:11. This section covers two crucial scenarios: Running an effect when a specific value changes (by putting that value in the dependency array). Running an effect only once (by providing an empty dependency array []).

Here's a summary of the rules for the dependency array:

Dependency Array When the Effect Runs Analogy (Gardener's To-Do List)
[dependency1, dependency2] After the first render, and only when any of the listed dependencies change. "Check the weather, but only when the season changes."
[] (empty array) Only once, after the initial component render. "Build the garden fence once, and then never again."
Omitted (no array provided) After every single render. This is rarely what you want and often causes bugs. "Water all the plants every time I even glance at the garden." (Chaos!)
Test your understanding!

Imagine a UserProfile component that fetches user data based on a userId prop.

function UserProfile({ userId }) {
  useEffect(() => {
    console.log(`Fetching data for user: ${userId}`);
    // fetch_data_from_api(userId);
  }, [userId]);

  return <h1>User: {userId}</h1>;
}

Initially, the component is rendered with userId={123}. A moment later, its parent component re-renders and passes userId={456}. Finally, something else causes the parent to re-render, but it passes the same userId={456} again.

How many times will "Fetching data for user..." be logged to the console, and what will the logs say?

Show answer

It will be logged twice.

  1. "Fetching data for user: 123": The effect runs after the initial render.
  2. "Fetching data for user: 456": The effect runs again because the userId dependency changed from 123 to 456.

It will not run a third time because on the final render, the userId dependency (456) did not change from its previous value.



3. Cleaning Up Your Effects

Some side effects need to be "undone." If you set up a sprinkler on a timer, you need to turn it off. If you subscribe to a real-time chat service, you need to unsubscribe when the user navigates away to prevent memory leaks and unnecessary network activity.

useEffect has a built-in mechanism for this. If you return a function from your effect, React will run it as a "cleanup" function.

This cleanup happens in two situations:

  1. When the component is removed from the screen (unmounts).
  2. Before the effect runs again (if its dependencies have changed).

This ensures you don't leave old subscriptions or timers running.

Master React Hooks in easy way | useEffect

This video from Nova Designs has an excellent explanation of the cleanup function, using a great example of an online/offline status indicator.

Watch from 03:43 to 05:31. Focus on the concept of the cleanup function and why it's crucial for preventing memory leaks. The example of adding and removing an event listener is a classic use case.

In our gardening analogy, the cleanup function is the "put away your tools" step. A good gardener doesn't leave the sprinklers running or the scarecrow up after the season is over. This principle is vital for writing robust, bug-free applications.


Conclusion

You've just learned one of the most powerful—and often misunderstood—concepts in modern React. By separating your rendering logic from your side effects, you create components that are more predictable, performant, and easier to debug.

Let's recap the key takeaways:

  • Side Effects are actions that interact with the world outside of a component's render cycle, like API calls or timers.
  • The useEffect Hook is the designated place to run side effects, ensuring they don't block UI rendering.
  • The Dependency Array gives you precise control over when your effect runs: only once, on every render, or when specific data changes.
  • The Cleanup Function is an optional return function from useEffect that prevents memory leaks by stopping timers, unsubscribing from services, etc.

You now have a complete overview of the fundamental hooks (useState and useEffect) needed to build modern React applications. With this foundation, you are officially ready to start your journey into Next.js!

In our next lesson, we will begin the "Next.js Pages and Routing" module. You'll learn how to initialize your first Next.js project and understand the file-based routing system that makes creating new pages so intuitive.