When useEffect runs
Tags: react, preact, javascript, useeffect
Published: 2023-02-10 18:39:22

---
title: When useEffect runs
published: true
description: useEffect can be challenging to understand, and manipulating exactly when it runs is a good skill to have!
tags: react, preact, javascript, useeffect
cover_image: https://images.unsplash.com/photo-1573447985340-c13fb23e2e8b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1590&q=80
canonical_url: https://cassidoo.co/post/when-useeffect-runs
---

`useEffect` is one of those React/Preact hooks that most people have a love/hate relationship with, but like it or not, it's good to understand how it works. This is not the first blog post on the subject, and it's certainly not going to be the last, but hopefully I can explain some things to you about when (and why!) it runs in your applications for you to use as a reference!

## Please tell my friend what `useEffect` actually is

Your friend asks a good question! First of all, let's talk about _side effects_ in your applications. When I say side effect, I mean it is something that happens when other things are changing.

For example, if I were to have a very simple `add` function:

```js
function add(x, y) {
	return x + y
}
```

I could make a side effect of some other variable changing, like so:

```js
let z = 10
function add(x, y) {
	z = z + x // this is the side effect, it does not change the return value
	return x + y
}
```

Changing that `z` variable in here does not change the return value of the function, it's just a side effect of adding `x` and `y`!

Now in React/Preact, it's a bit more complex, and side effects aren't always a good thing. And `useEffect` is "usually" for side effects. Developer [David Khourshid](https://twitter.com/DavidKPiano) aptly said that `useEffect` should probably have been named `useSynchronize`, because rather than it being, "an extra thing that should happen when state changes happen," it should be more like, "things that happen to stay in sync with certain state changes." 

## When does `useEffect` get called?

So, it does get a *little* hairy because `useEffect`s behavior has changed a bit across framework updates, but at a high level: it's called on component mount, and whenever anything in the dependency array changes. I'll explain this more deeply!

So using this as our base:

```js
useEffect(() => {
  // your fetch call, changes, etc
  return () => {
    // clean-up
  }
}, [dependencyArray]) // we're staying in sync with this
```

### The dependency array

That second parameter of `useEffect` is called the dependency array. There's 3 things that can happen here:

- If the dependency array is empty, `useEffect` is only called once (note: this has changed in React 18 in `development` and `strict mode` because of Suspense things, but this is how it is for Preact and pre-React 18 and I will talk about a workaround later in this post)
- If it doesn't exist (like it's omitted entirely), then `useEffect` is called on every state change
- If it has a variable in it, then `useEffect` is called when that variable changes

If that dependency array is populated, you can think of the `useEffect` function as staying "in sync" with the variables in the array.

### The return function

Whenever `useEffect` is about to be called again, or whenever the component is about to be dismounted/destroyed, the "clean-up function" is called.

Or to rephrase, React/Preact calls the clean-up functions when a component unmounts, or when an update is made and it needs to "cancel" the previous effect.

As another, more filled out, example:

```js
useEffect(() => {
  let isCurrent = true
  fetchUser(uid).then((user) => {
    if (isCurrent) setUser(user)
  })
  return () => {
    isCurrent = false
  }
}, [uid])
```

This might look a little confusing, but the way it works is when the component is mounted, the component will fetch the user.

If `uid` hasn't changed and the component stays mounted, `setUser` will be called. If `uid` changes in that time, `isCurrent` will be set to `false`, so `setUser` won't be called for that out-of-date HTTP call.

### Stopping `useEffect` from being called on mount

Besides controlling the dependency array variables, the only other thing you might want to consider is saying, "hey, I don't want this effect to be called on mount, but ONLY on updates in the dependency array." This is weird but it happens.

For this particular case, you'll want to bring in the `useRef` hook. I'm not going to explain what that hook does here because that deserves its own blog post ([this one is pretty good](https://www.robinwieruch.de/react-ref/) from [Robin Wieruch](https://twitter.com/rwieruch)). Let's assume you have some state variable called `syncWithMe` that you want to stay in sync with:

```js
const hasMounted = useRef(false);

useEffect(() => {
	if (hasMounted.current) {
		// code here only runs when syncWithMe changes!
	} else {
		hasMounted.current = true;
	}
}, [syncWithMe]);
```

This is called a "ref flag"! In this example, `hasMounted` acts as an instance variable that doesn't cause re-renders or effect changes (because it isn't a state variable). So, you set it to `true` when the component mounts, and then whenever `syncWithMe` changes, the effect function is called.

### Having `useEffect` called only on mount in React 18+

Because of how the new Suspense functionality works and a bunch of other changes that happened in React 18, `useEffect` needs to be manipulated more to run just once in `development` and `strict mode` (it should be fine in production but eh, this is still worth talking about). It'll look a lot like our previous example, but _opposite_:

```js
const hasMounted = useRef(false);
 
useEffect(() => {
  if (hasMounted.current) { return; }
  
  // do something
  
  hasMounted.current = true;
}, []);
```

## What if I don't want to use `useEffect` at all?

Then I think you should probably watch or read some thought-leadery content around why it's bad. Heh.

`useEffect` isn't bad, it just has its own time and place and a lot of people have Opinions™ about how it should be used. I do recommend [watching this talk](https://www.youtube.com/watch?v=HPoC-k7Rxwo) about `useEffect` in general. It is titled "Goodbye, `useEffect`" (once again from David Khourshid, who I referenced above), and explains some nuances of when you should and shouldn't use it.

Hopefully this post was useful for you as a reference!