We import the useEffect() hook from the react library by adding the code
import React, {useEffect } from 'react';
or...if you also want the useState() hook as well then...
import React, {useState, useEffect } from 'react';
The Effect Hook is used to call another function that does something
for us so there is nothing returned when we call the useEffect() function.
There are three key moments when the Effect Hook can be utilized:
When the component is first added, or mounted, to the DOM and renders.
When the state or props change, causing the component to re-render.
When the component is removed, or unmounted, from the DOM.
Then when you want to use the useEffect() command you could, eg...
useEffect(
() => {
alert(`Counter: ${myCount}`)
}
);
We are calling the useEffect
with a callback function () => {...}
which tells it to display an alert = Counter: 0
Some effects require cleanup. For example, we might want to add
event listeners to some element in the DOM, beyond the
JSX in our component.
When we add event listeners to the DOM, it is important to remove
those event listeners when we are done with them to avoid memory leaks!
Let’s consider the following effect:
useEffect(()=>{
document.addEventListener('keydown', handleKeyPress);
return () => {
document.removeEventListener(
'keydown', handleKeyPress);
};
})
If our effect didn’t return a cleanup function
import React, { useState, useEffect } from 'react'; export default function Counter() { const [clickCount, setClickCount] = useState(0); const increment = () => { setClickCount((prevClickCount) => prevClickCount + 1); } useEffect( () => { document.addEventListener('mousedown', increment); return () => { document.removeEventListener( 'mousedown', increment); } }); return ( <h1>Document Clicks: {clickCount}</h1> ); }In the code I created a function called increment which gets called on a mousedown event handler. This increment function uses a state setter callback function (setClickCount) to add 1 to clickCount.
import React, { useState, useEffect } from 'react';
export default function Timer() {
const [time, setTime] = useState(0);
const [name, setName] = useState("");
useEffect(() => {
const intervalId = setInterval(() => {
setTime((prev) => prev + 1);
}, 1000);
return () => {
clearInterval(intervalId);
};
}, []);
const handleChange =
({ target }) => setName(target.value);
return (
<>
<h1>Time: {time}</h1>
<input
value={name}
onChange={handleChange}
type='text' />
</>
);
}
The bit of code on the end of the useEffect() hook
It is common, when defining function components, to run an effect only when
the component mounts (renders the first time), but not when
the component re-renders.
The Effect Hook makes this very easy for us to do! If we want to only call
our effect after the first render, we pass an empty array to
useEffect() as the second argument.
This second argument is called the dependency array.
The dependency array is used to tell the useEffect() method when to
call our effect and when to skip it.
Our effect is always called after the first render but is
only
called again if something in our dependency array has
changed values between renders
.
useEffect(() => {
const intervalId = setInterval(() => {
setTime((prev) => prev + 1);
}, 1000);
return () => {
clearInterval(intervalId);
};
}, []);
The second argument is the empty dependency array...
In the following bit of code the Effect will be
run on the FIRST RENDER
But will then only be re-run when the value of count changes.
Because count is passed to
useEffect() as the second parameter it will ONLY get re-run when
the value of count changes.
useEffect( () => { document.title = `You clicked ${count} times`; } , [count] );First parameter in red
There are two main rules to keep in mind when using Hooks:
Only call Hooks at the top level
Only call Hooks from React functions
So DO NOT do this sort of thing
if (userName !== '') { useEffect(() => { alert("this is my code"); }); }
useEffect(() => { if (userName !== '') { alert("this is my code"); } });Which performs the check of the value of userName inside the useEffect hook statement.