useEffect
The useEffect Hook enables you to create side effects in your components.
Side effects include data fetching, direct DOM updates, and timers.
UseEffect accepts two arguments. The second input is optional.
useEffect(<function>, <dependence>).
Let us use a timer as an example.
Example:
Use setTimeout() to count one second after the initial 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);
}, 1000);
});
return I've rendered {count} times!
;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( );
But, wait!! It keeps counting when it should only count once!
Every render triggers the useEffect function. This means that when the count changes, a render occurs, triggering another effect.
This is not what we wanted. There are numerous strategies to control when side effects occur.
We should always add the second parameter, which accepts arrays. We can optionally send dependencies to useEffect in this array.
Example
1. No dependency passed:
useEffect(() => {
//Runs on every render
});
Example
2. An empty array:
useEffect(() => {
//Runs only on the first render
}, []);
Example
3. Props or state values:
useEffect(() => {
//Runs on the first render
//And any time any dependency value changes
}, [prop, state]);
So, to resolve this issue, let’s only apply this effect to the first render.
Example
Only apply the effect on the initial 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);
}, 1000);
}, []); // <- add empty brackets here
return I've rendered {count} times!
;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( );
Example
Here’s an example of a useEffect Hook that depends on a variable. If the count variable changes, the effect will rerun:
----- Example Mukavu -----
If there are many dependencies, they should be included to the useEffect dependency array.
Effect Cleanup
Some effects require cleanup to prevent memory leaks.
Timeouts, subscriptions, event listeners, and other effects that are no longer required should be deleted.
We accomplish this by adding a return function at the end of the useEffect Hook.
Example
Clean up the timer at the end of the useEffect Hook.
import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
let timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
return () => clearTimeout(timer)
}, []);
return I've rendered {count} times!
;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( );
NOTE: To clear the timer, we needed to give it a name.