Skip to main content
React Introduction
CHAPTER 13 Beginner

React useEffect Hook

Updated: May 13, 2026
25 min read

# React useEffect Hook

1. Introduction

React components are supposed to be "pure functions." They take props and state, and they return JSX. However, real applications need to do things that reach outside the component: fetching data from an API, talking to a database, manipulating the DOM, or setting up a timer. In React, these are called Side Effects. To handle them safely, we use the useEffect Hook.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand what a "Side Effect" is in React.
  • Use useEffect to execute code after a component renders.
  • Control exactly *when* an effect runs using the Dependency Array.
  • Clean up effects to prevent memory leaks.

3. Beginner-Friendly Explanations

What is useEffect?

useEffect tells React: *"Hey, after you finish putting the HTML on the screen, please run this block of code."* This is crucial because you don't want a heavy API fetch to freeze the screen while it loads. You want the screen to load immediately (maybe showing a spinner), and *then* the effect fetches the data in the background.

4. Syntax Explanation

Step 1: The Basic Setup

useEffect takes a callback function as its first argument. By default, it runs after every single render.

``jsx id="ch13_ex1" import { useState, useEffect } from 'react';

function Logger() { const [count, setCount] = useState(0);

// This will run when the component first loads, AND every time 'count' changes. useEffect(() => { console.log("The component rendered! Count is now: " + count); document.title = Clicked ${count} times`; });

return <button onClick={() => setCount(count + 1)}>Click Me</button>; }

123456
### Step 2: The Dependency Array (Crucial!)
Running an effect on *every* render is rarely what you want (especially for API calls, which would result in an infinite loop and crash your app). 
We control when `useEffect` runs by passing a second argument: an array of variables called the **Dependency Array**.

#### Scenario A: Run exactly ONCE (On Mount)
Pass an empty array `[]`. This tells React: "This effect depends on nothing. Run it once when the component loads, and never again."

jsx id="ch13_ex2" useEffect(() => { console.log("I only run once when the page loads!"); }, []); // Empty array!

12
#### Scenario B: Run when specific data changes
Pass a variable inside the array. React will only run the effect if that specific variable changed since the last render.

jsx id="ch13_ex3" const [searchQuery, setSearchQuery] = useState("");

useEffect(() => { console.log("The user typed a new search query! Let's fetch new data."); }, [searchQuery]); // Only runs when searchQuery changes!

123
### Step 3: Cleanup Functions
If you set up an interval timer or a WebSocket connection, you must clean it up when the component is removed from the screen, or you will cause a memory leak. You do this by returning a function from the effect.

jsx id="ch13_ex4" useEffect(() => { const timer = setInterval(() => console.log("Tick"), 1000);

// Cleanup function: runs when the component unmounts return () => { clearInterval(timer); }; }, []);

12345678910111213141516171819202122232425262728293031
## 5. Output Explanations
The dependency array is the most common source of bugs for React beginners.
- No array `()` => Runs on Mount + Every Update.
- Empty array `([])` => Runs on Mount only.
- Filled array `([x, y])` => Runs on Mount + Whenever `x` or `y` changes.

## 6. Real-World Examples
- Fetching data from a REST API when a dashboard loads.
- Subscribing to a real-time chat service.
- Tracking analytics (e.g., sending a "page viewed" event to Google Analytics).

## 7. Common Mistakes
- **The Infinite Loop API Fetch:** 
  Calling `setUsers(data)` inside a `useEffect` that has NO dependency array. 
  1. Component renders. 
  2. Effect fetches data and calls `setUsers`. 
  3. State changes, so Component re-renders. 
  4. Effect runs again. 
  5. Repeat infinitely until the browser crashes. ALWAYS use `[]` for API calls!

## 8. Best Practices
- Every variable from your component scope (state, props) that is used *inside* the `useEffect` must be listed in the dependency array. If you forget, your effect will use stale, outdated data.
- Keep your effects small and focused. It is better to have three small `useEffect` blocks that do different things than one massive one.

## 9. Exercises
1. Create a component that logs "Component Mounted" to the console only once.
2. Add a `useState` string variable. Add an effect that logs the string to the console *only* when the string changes.

## 10. Mini Project: Random Quote Fetcher
Let's build a component that uses `useEffect` to fetch data from a public API when it loads.

jsx id="ch13_proj1" // Example React component import React, { useState, useEffect } from 'react';

export default function QuoteOfTheDay() { const [quote, setQuote] = useState(""); const [author, setAuthor] = useState(""); const [isLoading, setIsLoading] = useState(true);

// Function to fetch data const fetchQuote = async () => { setIsLoading(true); try { // Using a free dummy API for quotes const response = await fetch('https://dummyjson.com/quotes/random'); const data = await response.json(); setQuote(data.quote); setAuthor(data.author); } catch (error) { setQuote("Failed to fetch quote."); } setIsLoading(false); };

// Run ONCE when component mounts useEffect(() => { fetchQuote(); }, []); // <-- Empty array is critical here!

return ( <div className="flex items-center justify-center min-h-screen bg-gray-100 p-4"> <div className="bg-white max-w-lg w-full p-8 rounded-2xl shadow-xl text-center"> <h1 className="text-xl font-bold text-gray-500 uppercase tracking-widest mb-6">Inspiration</h1> {isLoading ? ( <div className="animate-pulse flex flex-col space-y-4"> <div className="h-4 bg-gray-200 rounded w-3/4 mx-auto"></div> <div className="h-4 bg-gray-200 rounded w-1/2 mx-auto"></div> </div> ) : ( <> <p className="text-2xl italic text-gray-800 mb-6">"{quote}"</p> <p className="text-lg font-semibold text-blue-600">- {author}</p> </> )}

<button onClick={fetchQuote} disabled={isLoading} className="mt-8 bg-black text-white px-6 py-2 rounded-lg font-medium hover:bg-gray-800 disabled:bg-gray-400 transition" > Get Another Quote </button> </div> </div> ); } ``

11. Coding Challenges

Challenge 1: Create a
WindowWidth component. Use useEffect to attach a resize event listener to the window object. Update a state variable with the current window width. Don't forget the cleanup function to remove the event listener!

12. MCQs with Answers

Q1: What does an empty dependency array
[] signify in useEffect? A) The effect should never run. B) The effect should run on every render. C) The effect should run exactly once, when the component mounts. *Answer: C*

Q2: How do you prevent memory leaks from interval timers inside useEffect? A) By deleting the timer variable. B) By returning a cleanup function that calls clearInterval. C) React automatically clears timers for you. *Answer: B*

13. Interview Questions

  • Q: Explain what the Dependency Array does in useEffect.
  • Q: What happens if you update state inside a useEffect but forget to add a dependency array?

14. FAQs

Can I make the
useEffect callback function async directly? No, useEffect(async () => {}) is an anti-pattern and will cause issues. Instead, define an async function *inside* the effect and call it, exactly as we did in the Mini Project.

15. Summary

The
useEffect hook is your bridge to the outside world. It allows functional components to perform side effects safely. By mastering the Dependency Array, you gain precise control over when your effects execute, preventing infinite loops and ensuring high-performance applications.

16. Next Chapter Recommendation

useEffect` effectively replaced the old "Lifecycle Methods" used in Class components. In Chapter 14: React Component Lifecycle Basics, we will briefly look at the theoretical concept of a component's lifecycle (Mounting, Updating, Unmounting) to better understand exactly what React is doing under the hood.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·