Intro to React useEffect Hook
Tags: react, javascript, webdev, beginners
Published: 2021-11-16 01:01:17

## An introduction on how to use useEffect Hook

### What is a `useEffect` Hook?

> ### TLDR
> React `useEffect` is an alternative to the "old" `class` lifecycle methods/hooks.
>
> It can be used to manage side effects, such as network requests, or to run a piece of code when the component is mounted, updated, or unmounted.

### Longer version

> Prior to `React v16.8`, we can only enable a component
> to react to state changes using [lifecycle methods](https://reactjs.org/docs/state-and-lifecycle.html#adding-lifecycle-methods-to-a-class).

#### How to define a `useEffect`

```jsx
useEffect(() => { //(1) declaration
  // (2)effect
  return () => {
    // (3)cleanup 
  }
}, /* (4)dependency array */)
```

#### Here's an explanation of the above code:

1. We can declare an effect by calling either `React.useEffect` or `useEffect`
2. `effect` is the function that will be called when the component is mounted
OR when the dependency array changes.
3. `cleanup` is the function that will be called when the effect "unmounted".
4. `dependency array` is the array of values that will be passed to the `effect` function.
    - If there is no dependency array, the effect will be called every time the component is mounted.
    - If the array is empty, the effect will be called only once when the component is mounted.
    - If the array is not empty, the effect will be called every time the component is mounted and the dependency array changes.

<br />

### Examples

<br />

#### Increment a counter every second until it reaches 10
```jsx
function App() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    if (count < 10) {
      const interval = setInterval(() => {
        setCount(prev => prev + 1)
      }, 1000)

      // cleanup function
      return () => clearInterval(interval)
    }
  }, [count])

  // Render the component
}
```
[Link to Codepen](https://codepen.io/codegino/pen/JjyBPeO)

<br />

#### Basic fetch from an API

```jsx
function App() {
  const [data, setData] = useState([])

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(res => res.json())
      .then(data => setData(data))
  }, [])

  // Render the component
}
```
[Link to Codepen](https://codepen.io/codegino/pen/qBXKBeB)

<br />

#### Fetching with loading indicator + error handling - `then/catch/finally`

```jsx
function App() {
  const [data, setData] = React.useState()
  const [error, setError] = React.useState()
  const [isLoading, setIsLoading] = React.useState(false)

  React.useEffect(() => {
    setIsLoading(true)

    fetchData()
      .then(data => {
        setError(null)
        setData(data)
      })
      .catch(data => {
        // handle error case anyway you want
        setError(data)
        setData(null)
      })
      .finally(() => setIsLoading(false))
  }, [])

  // Render the component
}
```
[Link to Codepen](https://codepen.io/codegino/pen/WNEgqBw)

<br />

#### Fetching with loading indicator + error handling - `async/await`

```jsx
function App() {
  const [data, setData] = React.useState()
  const [error, setError] = React.useState()
  const [isLoading, setIsLoading] = React.useState(false)

  React.useEffect(() => {
    // yeah, this is weird
    (async () => {
      try {
        setIsLoading(true)
        const data = await fetchData()
        setError(null)
        setData(data)
      } catch(e) {
        // handle error case anyway you want
        setError(e)
        setData(null)
      }
      setIsLoading(false)
    })()
  }, [])

  // Render the component
}
```
[Link to Codepen](https://codepen.io/codegino/pen/jOLvgqB)

<br />

#### Store a value in localStorage everytime the key or value changes

```jsx
function App({ name }) {
  const [value, setValue] = useState(() => localStorage.getItem(name))

  useEffect(() => {
    localStorage.setItem(name, value)
  }, [name, value])
  // Ignore old keys for now

  // Render the component
}
```
[Link to Codepen](https://codepen.io/codegino/pen/vYJaBPV)

<br />

#### OR mimic a class lifecycle method

> Check this [blog](https://dev.to/carlogino/react-class-life-cycle-methods-to-useeffect-1kg0) on how to convert a class lifecycle methods to `useEffect` hooks

<br />

### Additional Note
- `useEffect` can only be used in functional components
- The order of `useEffect` declarations are important.
- `useEffect` in a custom hook is a great way to promote side effect reusability. I will discuss this in another blog.

<br />

## Conclusion
Compared to the old lifecycle methods, `useEffect` is much more powerful and flexible, making it an ideal choice when managing a side-effect.

### If you find it useful and you want to support me

<a href="https://www.buymeacoffee.com/codegino" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="37" width="174"></a>