Things that no one ever told you about useEffect() in React
Tags: webdev, react, javascript, beginners
Published: 2023-07-03 10:37:45

Hello there!

Welcome to another **React demystified** post. 

---

Last week, we covered the `useState()` hook. We took it to the fundamental level and asked ourselves the question - "**What exactly is state?**" 🤔.

{% embed https://dev.to/kokaneka/demystifying-reacts-usestate-hook-understanding-the-concept-of-state-e2n %}

---

In this week's post, we will look at the `useEffect()` hook. It is one of the complicated things that you need to deal with, while working on **functional React** components. But once you get the hang of it, there's no looking back. 

## `useEffect()` is an escape hatch
Look at this seemingly harmless piece of code & tell me what you think the output is going to be:

``` jsx
export default function App() {
  console.log('first');

  useEffect(() => {
    console.log('second');
  });

  console.log('third');
  return (
    <main>
      <h1>Hello World</h1>
    </main>
  )
}
```
At first glance, it looks as though the output will be 
- first
- second
- third

But, but, but...

The actual output is
- first 
- third 
- second

Let us understand why that is the case. 

If you notice closely, `useEffect` is a function, that takes in another function as its first argument. It then calls executes that function at a future point in time. Turns out, that it always calls the function after the React component is *rendered* and the *DOM is updated*. Even in case of the first render. If you are not clear about how a React component gets translated into something on the DOM, check out this video:

{% embed https://www.youtube.com/watch?v=mECV6nGOqNo %}

## The explanation
Now that we see `useEffect()` as a kind of escape hatch than anything else, the above behaviour makes more sense. 

What happens is this:
- `console.log(first)` is executed and we see **first**
- `useEffect` is executed and we supply a function to it
- `console.log(third)` is executed and we see **third** 
- React component is rendered, DOM update happens
- useEffect executes the function we supplied & we see **second**

"So what is the point of the useEffect hook if it comes into the picture after the DOM is updated?", you might ask. 

Well, it is to trigger **side-effects** (external). 

According to the [new React docs](https://react.dev/reference/react/useEffect), it is quite clear what useEffect is meant for:

![useEffect official](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irykc9oekc3zxj84wfgw.png)

So what does this sentence - "synchronize with external system" actually mean?

Well, simply put, it means all the things that are "outside" of the React component. That includes things like:
- **API** calls
- **DB** interactions
- **Subscribing** to external events

> So whenever you see any `useEffect`, now you know that it is an escape hatch to take you out of the *normal flow of code* and do things that deal with external systems. Although the code is placed inside of the function component (to take advantage of the **closure property** & **access local variables**), do not think of it as something that executes in the same flow. 

## The usage
With that understanding in place, let us look at a few use cases of `useEffect`:

### Side-effect on every render
This happens when we write code that looks something like the example above:
``` jsx
export default function App() {
  useEffect(() => {
    console.log('every render');
  });

  return (
    <main>
      <h1>Hello World</h1>
    </main>
  )
}
```
This kind of defeats the purpose of `useEffect` as it runs the side-effect **every time** the component is rendered. 

### side-effect once
If we pass an empty array as the second argument to useEffect, we are letting it know to run our function only once - **right after the first render**. 
``` jsx
export default function App() {
  useEffect(() => {
    console.log('after first render');
  }, []);

  return (
    <main>
      <h1>Hello World</h1>
    </main>
  )
}
```

### side-effect on dependency change
In this use-case, we are instructing `useEffect` to run the function every time a **dependency is changed** (by specifying the dependency in the array). This might be useful if the side-effect is dependent on the dependency. 
``` jsx
export default function App() {
  useEffect(() => {
    console.log('count changed');
  }, [count]);

  return (
    <main>
      <h1>Hello World</h1>
    </main>
  )
}
```

### summary
This sketchnote summarises it well:
![useEffect summary](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8v5e8jw2pkemz63n3f6y.jpeg)

Hope that this article cleared up a lot of things like the need for something like `useEffect()` in the React paradigm. Also, hope that the 3 use cases are clear and that you will feel more confident in your "effects" henceforth. 

Cheers! 🙌🏾