What is UseEffect Hook & How to Manage Side Effects in React?

In React, managing side effects and handling component lifecycle events is an essential part of building dynamic and responsive applications. The UseEffect hook is a fundamental tool for achieving these goals in functional components.
In this comprehensive guide, we’ll dive deep into the UseEffect hook, exploring its purpose, syntax, and various use cases.
By the end of this blog, you’ll have a solid understanding of how to leverage UseEffect to manage side effects effectively in your React applications.
What is the UseEffect Hook?
The UseEffect hook is part of the React Hooks API, introduced in React 16.8. It allows you to perform side effects in your functional components. Side effects are actions that occur in a component other than rendering, such as data fetching, DOM manipulation, and setting up subscriptions.
Syntax of UseEffect
Before we delve into practical examples, let’s look at the syntax of the useEffect hook:
import React, { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// Side effect code goes here
}, [dependency1, dependency2]);
}
- The first argument is a function that contains the code for your side effect.
- The second argument is an optional array of dependencies. If provided, the effect will only run when one or more of these dependencies change. If omitted, the effect runs after every render.
To read more about useState Hook in React & how to manage state in functional components, refer to our blog What is useState Hook in React & How to Manage State in Functional Components
Basic Usage: Fetching Data
One of the most common use cases for useEffect is data fetching. Let’s create a simple component that fetches and displays data from an API when it mounts.
import React, { useState, useEffect } from 'react';
function DataFetchingComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((result) => setData(result))
.catch((error) => console.error(error));
}, []); // Empty dependency array, runs only once
return (
<div>
{data ? (
<ul>
{data.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
) : (
<p>Loading...</p>
)}
</div>
);
}
In this example, we use useState to manage the fetched data and useEffect to make the API request when the component mounts. Since we provide an empty dependency array, the effect runs once after the initial render.
Managing Cleanup with UseEffect
useEffect also allows us to clean up resources when a component unmounts or when dependencies change. This is important to prevent memory leaks. Let’s create a timer that starts when the component mounts and stops when it unmounts:
import React, { useState, useEffect } from 'react';
function TimerComponent() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setSeconds((prevSeconds) => prevSeconds + 1);
}, 1000);
// Cleanup function
return () => {
clearInterval(intervalId);
};
}, []); // Empty dependency array, runs only once
return <div>Time: {seconds} seconds</div>;
}
Here, we use clearInterval in the cleanup function returned by UseEffect to stop the timer when the component unmounts. This ensures that we don’t have a lingering timer after the component is removed from the DOM.
Conditional Effects
Sometimes, you may want to conditionally run an effect based on a specific condition. For example, you might want to fetch data only when a certain prop changes. You can achieve this by including that prop in the dependency array:
import React, { useState, useEffect } from 'react';
function ConditionalDataFetching({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
if (userId) {
fetch(`https://api.example.com/user/${userId}`)
.then((response) => response.json())
.then((result) => setData(result))
.catch((error) => console.error(error));
}
}, [userId]); // Include userId in the dependency array
return (
<div>
{data ? (
<p>User ID: {data.id}, Name: {data.name}</p>
) : (
<p>Loading...</p>
)}
</div>
);
}
In this example, the effect only runs when the userId prop changes. This prevents unnecessary API calls when other props or state variables change.
To read more about creating API Requests with React & Axios, refer to our blog How to Create API Requests With React & Axios in 2023
Conclusion
The UseEffect hook is a powerful tool for managing side effects and handling component lifecycle events in React functional components. Whether you’re fetching data, setting up timers, or performing cleanup, useEffect provides a clean and declarative way to manage side effects. Understanding its syntax and usage is essential for building dynamic and responsive React applications.