React: useEffect() Hook
The useEffect
Hook allows you to perform side effects in your components. It takes two arguments, first is setup function, a function with your effect's logic. and second is dependencies, which is an optional argument
useEffect(<setup>, <dependencies>)
Example:
Dependencies is an optional argument, so when you don't pass any dependency, useEffect
will run after every render.
import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 3000);
});
return <h1>Count:{count}</h1>;
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Timer />);
https://codesandbox.io/p/sandbox/useeffectexample-qqpxw2?file=%2Fsrc%2Findex.js%3A13%2C15
In the above example, count will be increase by 1 after every 3 seconds.
But sometimes these side effects need to be control, for that, we pass the second argument Dependency Array.
To run the useEffect
at the initial render only, we pass an empty array.
Example:
import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 2000);
}, []);
return <h1>Count: {count}</h1>;
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Timer />);
https://codesandbox.io/p/sandbox/useeffectexample-2-v4ft5v?file=%2Fsrc%2Findex.js%3A9%2C10
In some condition useEffect
is dependent on some variable, we have to pass that variable in the dependency array to run the useEffect
when that variable gets update. If there are multiple dependencies, then they should be included in the dependency array.
Example:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Counter() {
const [count, setCount] = useState(0);
const [total, setTotal] = useState(0);
const handleIncrement = () => {
setCount(count + 1);
};
const handleDecrement = () => {
setCount(count - 1);
};
useEffect(() => {
setTotal(() => count * 2);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={handleIncrement}>Increment</button>
<button onClick={handleDecrement}>Decrement</button>
<p>Total: {total}</p>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Counter />);
https://codesandbox.io/p/sandbox/useeffectexample-3-y2njcm?file=%2Fsrc%2Findex.js%3A10%2C23
Some effects require cleanup, to avoid memory leaks. Some effects that are no longer needed should be disposed. We can do this by including the return function at the end of the useEffect hook.
Example:
import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";
function Counter() {
const [count, setCount] = useState(0);
const [total, setTotal] = useState(0);
useEffect(() => {
let t = setTimeout(() => {
setCount((count) => count + 1);
}, 2000);
return () => clearTimeout(t);
});
useEffect(() => {
setTotal(() => count * 2);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<p>Total: {total}</p>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Counter />);
https://codesandbox.io/p/sandbox/useeffectexample-4-dvdl3m?file=%2Fsrc%2Findex.js%3A7%2C10