React useEffect

Image of Author
October 11, 2022 (last updated October 18, 2022)

I'm referring to React <= 18. New APIs are in the works that could perhaps invalidate some of the below points.

useEffect is hard to understand. But perhaps one of the most important things to note is that you shouldn't be using it very much!

Try to avoid using useEffect

This is a long, but good, read: https://beta.reactjs.org/learn/you-might-not-need-an-effect. Here are some powerful quotes from it.

Effects are an escape hatch from the React paradigm. They let you “step outside” of React and synchronize your components with some external system like a non-React widget, network, or the browser DOM. If there is no external system involved (for example, if you want to update a component’s state when some props or state change), you shouldn’t need an Effect. Removing unnecessary Effects will make your code easier to follow, faster to run, and less error-prone.

You don’t need Effects to transform data for rendering.

One of the many good ideas in that article is using key to reset the state of a component. There is more on that approach in Preserving and Resetting State - Resetting state with a key

One of the more complex avoidances is Storing information from previous renders

In my opinion, the key takeaway from this article is asking yourself a few question.

Am I updating state based on a particular event? If so, consider an event-handler like on-click.

Am I updating state based on a change in state? If so, this can likely be computed inline on each state change, and does not need to live in state at all. When the performance of your "calculated state" becomes an issue, you can reach for useMemo or useCallback.

The Recap at the bottom is full of good bullet points:

  • If you can calculate something during render, you don’t need an Effect.
  • To cache expensive calculations, add useMemo instead of useEffect.
  • To reset the state of an entire component tree, pass a different key to it.
  • To reset a particular bit of state in response to a prop change, set it during rendering.
  • Code that needs to run because a component was displayed should be in Effects, the rest should be in events.
  • If you need to update the state of several components, it’s better to do it during a single event.
  • Whenever you try to synchronize state variables in different components, consider lifting state up.
  • You can fetch data with Effects, but you need to implement cleanup to avoid race conditions.

Common reasons to actually use useEffect

On component render

function Component() {
  useEffect(() => {
    // do something once
  }, []);
}

Fetching data

The most important point here is to not forget about the cleanup function! The cleanup function is an optional return value you can supply. It has access to local variables within your useEffect function, meaning you can use it to ignore previous fetches!