useEffect Hook in React

Introduction

Developers often need to perform operations such as:

  • Fetching API data
  • Updating the document title
  • Setting timers
  • Handling subscriptions
  • Working with local storage

These operations are called Side Effects in React.

Before React Hooks were introduced, side effects were mainly handled using lifecycle methods in class components such as:

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

However, lifecycle methods made components more complex and difficult to manage.

The useEffect Hook allows functional components to perform side effects easily and efficiently.

What is useEffect Hook?

The useEffect Hook is a React Hook used to handle side effects inside functional components.

It allows React components to:

  • Run code after rendering
  • Fetch data
  • Update the DOM
  • Manage timers
  • Clean up resources

What are Side Effects?

Side effects are operations that affect something outside the component.

Examples:

  • API calls
  • Timers
  • Event listeners
  • Updating browser title
  • Local storage access

Why useEffect is Used?

React components mainly focus on rendering UI.

However, applications also need:

  • External data fetching
  • Background operations
  • Dynamic updates

useEffect helps manage these operations cleanly.

Syntax of the useEffect Hook

Basic syntax:


useEffect(() => {
 // Side effect code
}, []);

Understanding the Syntax

First Argument

A callback function containing side effect logic.

Second Argument

Dependency array controlling when the effect runs.

Basic Example of useEffect


import { useEffect } from "react";
function App() {
 useEffect(() => {
   console.log("Component Rendered");
 }, []);
   return <h1>Hello React</h1>;
}
export default App;

Output

Component Rendered

The effect runs after the component renders.

useEffect Without Dependency Array


useEffect(() => {
 console.log("Runs Every Render");
});

Behavior

The effect runs:

  1. After every render
  2. After every state update

useEffect with Empty Dependency Array


useEffect(() => {
 console.log("Runs Once");
}, []);

Behavior

Runs only once when the component mounts.

Equivalent to:


componentDidMount

useEffect with Dependencies


import { useState, useEffect }
from "react";
function App() {
 const [count, setCount] = useState(0);
 useEffect(() => {
   console.log("Count Updated");
 }, [count]);
 return (
   <button onClick={() => setCount(count + 1) } >
     {count}
   </button>
 );
}
}

Behavior

Effect runs whenever

  • count changes

Real-Life Example of useEffect

Suppose you are building an e-commerce website.

You may need:

  • Product data fetching
  • Cart synchronization
  • Authentication checks
  • Search filtering

useEffect handles these operations efficiently.

Fetching API Data with useEffect

One of the most common uses of useEffect is API fetching.

Example


import { useState, useEffect }
from "react";
function App() {
 const [users, setUsers] =
   useState([]);
 useEffect(() => {
   fetch(
     "https://jsonplaceholder.typicode.com/users"
   )
     .then((response) =>
       response.json()
     )
     .then((data) =>
       setUsers(data)
     );
 }, []);
 return (
   <div>
     {
       users.map((user) => (
         <h2 key={user.id}>
           {user.name}
         </h2>
       ))
     }
   </div>
 );
}

Output

User data appears after fetching from API.

Cleanup Function in useEffect

Sometimes effects need cleanup.

Examples:

  • Timers
  • Event listeners
  • Subscriptions

React provides cleanup functions.

Syntax of Cleanup Function


useEffect(() => {
 return () => {
   // Cleanup code
 };
}, []);

Timer Example with Cleanup


import { useEffect } from "react";
function App() {
 useEffect(() => {
   const timer =
     setInterval(() => {
       console.log("Running");
     }, 1000);
   return () => {
     clearInterval(timer);
   };
 }, []);
 return <h1>Timer Example</h1>;
}

Why is cleanup important?

Cleanup prevents:

  • Memory leaks
  • Unnecessary background tasks
  • Performance issues

useEffect vs Lifecycle Methods

Before Hooks, lifecycle methods handled side effects.

useEffect combines:

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

Comparison Table

Feature useEffect Hook Class Lifecycle Methods
Syntax Simple Complex
Functional Components Supported Not Supported
Side Effects Supported Supported
Cleanup Easy More Complex
Modern Usage Recommended Less Common

Multiple useEffect Hooks

Components can use multiple effects.

Example


useEffect(() => {
 console.log("Effect One");
}, []);
useEffect(() => {
 console.log("Effect Two");
}, []);

Benefits of Multiple Effects

  • Cleaner code
  • Better separation of logic
  • Easier maintenance

Dependency Array in useEffect

Dependency array controls effect execution.

Types of Dependency Arrays

Dependency Array Behavior
No Array Runs every render
Empty Array [] Runs once
[value] Runs when value changes

Common useEffect Use Cases

useEffect is commonly used for:

  • API calls
  • Timers
  • Authentication checks
  • DOM updates
  • Event listeners
  • Data synchronization

Advantages of useEffect Hook

Feature Benefit
Side Effect Handling Better application control
Functional Components Modern React development
Cleaner Code Easier readability
Dependency Control Optimized rendering
Cleanup Support Prevents memory leaks

Common Mistakes in useEffect

1. Missing Dependency Array

Wrong:


useEffect(() => {
 console.log("Hello");
});

Runs after every render.

2. Infinite Loop Problem

Wrong:


useEffect(() => {
 setCount(count + 1);
}, [count]);

This creates infinite re-renders.

3. Forgetting Cleanup

Timers and listeners should always be cleaned.

4. Using Too Many Effects

Avoid unnecessary effects.

5. Incorrect Dependencies

Missing dependencies may cause bugs.

Best Practices for useEffect

  • Use dependency arrays properly
  • Keep effects focused
  • Always clean up timers/listeners
  • Avoid unnecessary re-renders
  • Separate unrelated effects
  • Avoid infinite loops

Real-World Applications of useEffect

useEffect is heavily used in:

  • Social media apps
  • E-commerce websites
  • Banking systems
  • Dashboards
  • Chat applications

Examples:

  1. Fetching products
  2. User authentication
  3. Notifications
  4. Timers
  5. Real-time updates

useEffect vs Normal JavaScript Functions

Feature useEffect JavaScript Function
React Lifecycle Access Yes No
Side Effect Handling Yes Limited
Dependency Tracking Yes No
Automatic Re-run Yes No

useEffect Hook – Interview Questions

Q 1: What is the purpose of useEffect?
Ans: useEffect is used to perform side effects such as API calls, subscriptions, and DOM updates.
Q 2: When does useEffect run?
Ans: It runs after the component renders.
Q 3: What is the dependency array in useEffect?
Ans: It controls when the effect runs based on state or prop changes.
Q 4: How do you run useEffect only once?
Ans: By passing an empty dependency array [].
Q 5: Can useEffect replace lifecycle methods?
Ans: Yes, it can replace componentDidMount, componentDidUpdate, and componentWillUnmount.

useEffect Hook– Objective Questions (MCQs)

Q1. What is the primary purpose of the useEffect hook in React?






Q2. When does the effect run if no dependency array is provided?






Q3. How do you run an effect only once after the first render?






Q4. Which of the following is a valid cleanup in useEffect?






Q5. Which of these is a side effect suitable for useEffect?






Conclusion

The useEffect Hook is one of the most important Hooks in React because it allows functional components to handle side effects efficiently. It simplifies lifecycle management and makes React applications cleaner and easier to maintain.

useEffect is commonly used for:

  • API fetching
  • Timers
  • Event listeners
  • Authentication
  • DOM updates

Continue Learning React