Skip to main content

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:

  1. No dependencies:
useEffect(() => {
//Runs on every render
});
  1. An empty array
useEffect(() => {
//Runs only on the first render
}, []);
  1. 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