The useEffect Hook allows a React component to perform side effects. Side effects are operations that happen outside the normal process of calculating and rendering JSX, such as fetching data, changing the document title, setting up timers, or working with browser APIs.
useEffect Hook is commonly used
when a component needs to synchronize with something outside the
React rendering process.
useEffect is a React Hook used to perform side effects
from a functional component.
import { useEffect } from "react";
function App() {
useEffect(() => {
console.log("Effect executed");
});
return (
<h1>
Hello React
</h1>
);
}
The Hook is imported from React.
import { useEffect } from "react";
If you use both useState and
useEffect, both can be imported together.
import {
useState,
useEffect
} from "react";
The basic syntax is:
useEffect(() => {
// side effect
});
The first argument is a function containing the effect logic.
An effect is run after React has rendered the component.
function App() {
useEffect(() => {
console.log("Component rendered");
});
return (
<h1>
Hello
</h1>
);
}
An empty dependency array tells React that the effect does not depend on changing values from the component.
useEffect(() => {
console.log("Effect executed");
}, []);
This pattern is commonly used for setup work when the component is mounted.
A dependency can be placed inside the dependency array.
useEffect(() => {
console.log("Count changed");
}, [count]);
The effect runs after rendering when the value of
count changes.
import {
useState,
useEffect
} from "react";
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Count:", count);
}, [count]);
return (
<button
onClick={() =>
setCount(count + 1)
}
>
Count: {count}
</button>
);
}
export default App;
One simple example of an effect is changing the browser document title.
useEffect(() => {
document.title = "React Tutorial";
}, []);
The browser tab title can be updated using the
document.title property.
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
Whenever count changes, the document title is updated.
The dependency array tells React which values the effect uses for synchronization.
useEffect(() => {
console.log(name);
}, [name]);
When name changes, React runs the effect after the
corresponding render.
More than one dependency can be specified.
useEffect(() => {
console.log(name);
console.log(age);
}, [name, age]);
The effect is synchronized when either dependency changes.
If no dependency array is provided, the effect runs after every completed render.
useEffect(() => {
console.log("Effect executed");
});
This should be used carefully because frequent effects may perform unnecessary work.
An empty dependency array is written as [].
useEffect(() => {
console.log("Initial effect");
}, []);
This is commonly used when the effect does not need to react to changing component values.
A common use of useEffect is starting data fetching when a
component needs external data.
useEffect(() => {
fetch("https://example.com/api/users")
.then(response => response.json())
.then(data => {
console.log(data);
});
}, []);
Fetched data can be stored in state.
import {
useState,
useEffect
} from "react";
function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://example.com/api/users")
.then(response => response.json())
.then(data => {
setUsers(data);
});
}, []);
return (
<div>
{users.map(user => (
<p key={user.id}>
{user.name}
</p>
))}
</div>
);
}
A loading state can be used while asynchronous data is being retrieved.
const [loading, setLoading] =
useState(true);
useEffect(() => {
fetch("https://example.com/api/users")
.then(response => response.json())
.then(data => {
setUsers(data);
setLoading(false);
});
}, []);
Effects can be used to create timers or intervals.
useEffect(() => {
const timer = setTimeout(() => {
console.log("Timer completed");
}, 2000);
}, []);
Timers created by an effect may need cleanup.
An effect can return a cleanup function. Cleanup is useful for removing subscriptions, timers, event listeners, and other resources created by the effect.
useEffect(() => {
const timer = setInterval(() => {
console.log("Running");
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
Cleanup prevents resources created by an effect from continuing after they are no longer needed.
Cleanup can be useful for:
useEffect(() => {
function handleResize() {
console.log(window.innerWidth);
}
window.addEventListener(
"resize",
handleResize
);
return () => {
window.removeEventListener(
"resize",
handleResize
);
};
}, []);
The cleanup function removes the event listener.
An effect can depend on a prop.
function Student({ studentId }) {
useEffect(() => {
console.log(
"Student ID:",
studentId
);
}, [studentId]);
return (
<h2>
Student
</h2>
);
}
When studentId changes, the effect runs after the render.
The main idea behind effects is synchronization with systems outside the normal React rendering calculation.
Examples include:
Not every calculation needs an effect. If a value can be calculated directly from props or state during rendering, an effect may not be necessary.
For example:
const fullName =
firstName + " " + lastName;
This simple calculation can normally be performed directly instead of
using useEffect.
An effect can contain logic that should happen when a dependency changes.
useEffect(() => {
if (isLoggedIn) {
console.log("User is logged in");
}
}, [isLoggedIn]);
A component can have multiple effects when they represent separate synchronization tasks.
useEffect(() => {
document.title = "React App";
}, []);
useEffect(() => {
console.log("Count changed");
}, [count]);
Keeping unrelated effects separate can make the component easier to understand.
useEffect.import {
useState,
useEffect
} from "react";
function App() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setSeconds(
previousSeconds =>
previousSeconds + 1
);
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return (
<div>
<h1>
Seconds: {seconds}
</h1>
</div>
);
}
export default App;
import {
useState,
useEffect
} from "react";
function App() {
const [users, setUsers] = useState([]);
const [loading, setLoading] =
useState(true);
useEffect(() => {
fetch("https://example.com/api/users")
.then(response => response.json())
.then(data => {
setUsers(data);
setLoading(false);
});
}, []);
if (loading) {
return (
<h2>
Loading...
</h2>
);
}
return (
<div>
{users.map(user => (
<p key={user.id}>
{user.name}
</p>
))}
</div>
);
}
export default App;
A simple way to understand an effect is:
Render
↓
UI Update
↓
Effect
↓
External Synchronization
↓
Cleanup when needed
useEffect from React.useEffect is used for side effects and synchronization.
Question: What is the main purpose of the
useEffect Hook in React?