The useEffect() Hook lets you run side effects in React functional components:
document.title)It replaces common class component lifecycle methods:
componentDidMount → Run once on mountcomponentDidUpdate → Run when state/props changecomponentWillUnmount → Run cleanup before unmountuseEffect can behave like mount, update, or unmount lifecycle methods.| Lifecycle Phase | useEffect Configuration |
|---|---|
| componentDidMount | useEffect(() => {...}, []) |
| componentDidUpdate | useEffect(() => {...}, [state]) |
| componentWillUnmount | return () => {...} inside useEffect |
Basic useEffect() syntax with optional cleanup and dependencies:
// Basic useEffect syntax with optional cleanup and dependencies
useEffect(() => {
doSideEffect();
return () => {
cleanUpSideEffect();
};
}, [dependencies]);
If you omit the dependency array, the effect runs after every render: initial mount and every state/prop update.
// useEffect without dependencies runs after every render
import React, { useState, useEffect } from "react";
function EveryRenderExample() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Rendered or re-rendered");
});
return (
<div className="text-center">
<h4>Count: {count}</h4>
<button className="btn btn-primary" onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
"Rendered or re-rendered" appears in the console.count changes, the component re-renders, and the effect runs again.Passing an empty dependency array makes the effect run only once after the component mounts (similar to componentDidMount).
// Effect with empty dependency array runs only once on mount
import React, { useEffect } from "react";
function MountExample() {
useEffect(() => {
console.log("Component mounted");
document.title = "Welcome to React Hooks!";
}, []);
return <h5 className="text-center">Hello React!</h5>;
}
"Welcome to React Hooks!".Add values to the dependency array to run the effect only when those values change.
// Effect runs only when the specified dependency changes
import React, { useState, useEffect } from "react";
function UpdateExample() {
const [count, setCount] = useState(0);
const [name, setName] = useState("");
useEffect(() => {
console.log("Count changed:", count);
}, [count]);
return (
<div className="text-center">
<input
placeholder="Enter name"
className="form-control mb-2"
onChange={(e) => setName(e.target.value)}
/>
<p>Name: {name}</p>
<p>Count: {count}</p>
<button className="btn btn-primary" onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
name but does not trigger the effect.count and triggers the effect, logging the new value.componentDidUpdate for a specific piece of state.Returning a function from inside useEffect lets you clean up timers, listeners, or subscriptions when the component unmounts (similar to componentWillUnmount).
// Timer with cleanup to clear the interval when component unmounts
import React, { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((s) => s + 1);
}, 1000);
return () => {
clearInterval(interval);
console.log("Timer stopped");
};
}, []);
return <h5 className="text-center">Time: {seconds}s</h5>;
}
seconds every second.clearInterval stops the timer.A very common use of useEffect is data fetching when the component first loads.
// Fetch a user list once when the component is mounted
import React, { useState, useEffect } from "react";
function FetchDataExample() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => setUsers(data));
}, []);
return (
<div>
<h5>User List</h5>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
setUsers updates state and the list of users is rendered.return function inside useEffect to avoid memory leaks.useEffect hooks in the same component to separate concerns.[] so it runs only once.useEffect cleanup when unmounted.document.title to show the current count (e.g., "Messages (3)") using useEffect.Goal: Use useEffect() to simulate React lifecycle behavior, manage side effects, and implement proper cleanup for stable, bug-free components.