In this article, we will learn about another React hook called useEffect(), through this article you will be able to understand what is react useEffect Hook and how to use useEffect() hook in react, this is most communally used hook after useState() hook, we mostly use this hook in every component on react now first let’s understand what react useEffect Hook is
What is the useEffect Hook in React?
The useEffect
Hook is a function that allows you to perform side effects in functional components. A side effect is any operation that can be done but doesn’t directly produce any output, such as fetching the API with useEffect Hook, manually changing the DOM on component load or on state change using useEffect
useEffect() Combines the functionality of class component lifecycle methods componentDidMount
, componentDidUpdate
, and componentWillUnmount
.
Let’s go through a basic example updating the text on tile tag through useEffect Hook
import React, { useState, useEffect } from 'react';
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default App
In the above code we are using useEffect to updates the document title using the browser API document.title
. The effect runs on every render, including the initial render.
Dependencies in useEffect
The above example is the side effect we want to do with the title of the document, which is outside of the component, lets learn one more dependency which we can add to useEffect to perform certain oprations
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [dependency]);
In above code we are passing the array of decencies which we can pass to the use Effect function, the useEffect function then trigger only if there is a change in dependency, so change in dependency means you can relate is to the state, so we can also trigger use effect when some state changes to apply our side effects, so if we want to trigger use effect only if the count updates so we can use the below method
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
In this example, we pass [count]
as the second argument to useEffect
. This tells React to only execute the effect when the count
state variable changes.
and is you want to run useEffect on component load only or component mount and unmount which will execute only once, you can just pass [] empty array as dependency, also we use that method most to fetch the API on component load
Fetch API in useEffect react
import React, { useState, useEffect } from 'react';
function FetchData() {
const [data, setData] = useState([]);
useEffect(() => {
async function fetchData() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
setData(data);
}
fetchData();
}, []);
return (
<div>
<h1>Fetched Data</h1>
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
}
export default FetchData;
Inside the effect function, we define an asynchronous function fetchData()
to make the API request.
We pass an empty array []
as the second argument to useEffect
to ensure the effect only runs once on the initial render.
What is the useEffect
 Cleanup Function?
The cleanup function is defined within the useEffect
 hook and is executed under two main circumstances:
- When the component unmounts: This is when the component is removed from the DOM, and the cleanup function can be used to free up resources.
- Before the effect runs again: If the component re-renders and the dependencies specified in theÂ
useEffect
 change, the cleanup function from the previous render is called before executing the new effect. This ensures that any previous side effects are properly managed before new ones are applied.
import React, { useEffect, useState } from 'react';
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount(prevCount => prevCount + 1);
}, 1000);
// Cleanup function to clear the timer
return () => clearInterval(timer);
}, []);
return <div>Count: {count}</div>;
}
In this example, a timer is set up when the component mounts. The cleanup function clears the timer when the component unmounts or before the effect runs again
Why is the Cleanup Function Important?
- Preventing Memory Leaks: If resources like timers, subscriptions, or event listeners are not cleaned up, they can continue to run in the background, consuming memory and potentially leading to performance issues.
- Avoiding Race Conditions: When dealing with asynchronous operations, the cleanup function can cancel any ongoing requests or operations, ensuring that updates are only applied if the component is still mounted
Below are the most common way we mostly use useEffect
- Clearing Timers: As shown in the example, to avoid leaving timers running when a component unmounts.
- Removing Event Listeners: If you add event listeners in your effect, you should remove them in the cleanup function to prevent memory leaks and unintended behavior.
- Unsubscribing from Services: For example, if you’re using WebSocket connections or any subscription-based service, you should unsubscribe when the component unmounts
Below is the working example of use effect you can go through
https://stackblitz.com/~/github.com/mohit49/useEffect-update-title-tag?file=src/App.jsx:L1-L23