The useEffect
Hook in React allows you to perform side effects in your function components. Side effects are operations that can affect other components and cannot be done during rendering. Common examples include fetching data, directly interacting with the DOM, setting up subscriptions, and more.
import { useEffect } from "react";
function ExampleComponent() {
useEffect(() => {
// Code to run on component mount
console.log("Component mounted");
return () => {
// Cleanup code for component unmount
console.log("Component unmounted");
};
}, []); // Empty dependency array means this effect runs only on mount and unmount
return <div>Hello, world!</div>;
}
export default ExampleComponent;
useEffect
Work?The useEffect
function takes two arguments:
The side effect function can optionally return a cleanup function. This cleanup function is called before:
The dependency array is a crucial feature of useEffect
. It determines when the useEffect callback should be executed:
No dependency array: The effect runs after every rendering.
useEffect(() => {
document.title = `Updated on every render`;
});
Empty dependency array ([]
): The effect runs once after the initial render (similar to componentDidMount
in class components).
useEffect(() => {
fetchData();
}, []);
Array with dependencies: The effect runs after the initial render and after every re-render if (and only if) any value in the dependency array changes.
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
}, [props.source]); // Runs only if props.source changes
useEffect
One common use case is fetching data from an API:
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
};
fetchData();
}, []); // Dependency array is empty, so this runs only once
useEffect
is also useful for setting up and tearing down subscriptions:
const [status, setStatus] = useState('Not Connected');
useEffect(() => {
const onStatusChange = newStatus => setStatus(newStatus);
SomeAPI.subscribe(onStatusChange);
return () => {
SomeAPI.unsubscribe(onStatusChange);
};
}, []); // Runs only once
You can use useEffect
to perform direct DOM manipulations, which are typically done after the component renders:
useEffect(() => {
const timer = setTimeout(() => {
alert('This message is shown after 3 seconds');
}, 3000);
return () => clearTimeout(timer);
}, []); // Runs only once
Do not perform side effects directly in the body of the component: This could lead to performance issues and bugs.
Place useEffect
at the top level in your component: Like other Hooks, useEffect
should not be called conditionally or inside loops or nested functions.
Use multiple effects to separate concerns: Each effect should be responsible for a single feature or side effect.