useEffect
The useEffect Hook allows you to perform side effects in your components.
Some examples of side effects are:
- fetching data,
- directly updating the DOM,
- Timers
useEffect accepts two arguments. The second argument is optional (but highly recommended).
useEffect(<function>, <dependency>)
Let's use a timer as an example. Use setTimeout() to count 1 second
after initial render:
import { useState, useEffect } from "react"
const App = () => {
const [count, setCount] = useState(0)
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1)
}, 1000)
});
return <h1>I've rendered {count} times!</h1>
}
export default App
But wait!! It keeps counting even though it should only count once!
useEffect runs on every render. That means that when the
count changes, the state changes so a render happens,
which then triggers another effect etc...
This is not what we want. There are several ways to control when side effects run.
We should always include the second parameter which accepts
an array. We can optionally pass dependencies to useEffect
in this array:
- No dependencies:
useEffect(() => {
//Runs on every render
});
- An empty array
useEffect(() => {
//Runs only on the first render
}, []);
- One or multiple props or state values
useEffect(() => {
//Runs on the first render
//And any time any dependency value changes
}, [prop, state]);
Example
import { useState, useEffect } from "react"
const App = () => {
const [count, setCount] = useState(0)
const [updateCount, setUpdate] = useState(false)
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1)
}, 1000);
}, [updateCount])
return(
<div>
<h1>I've rendered {count} times!</h1>
<button onClick={ () => setUpdate(!updateCount) }>Update</button>
</div>
)
}
export default App