React useEffect Hook

Ceci García García
Trabe
Published in
3 min readMar 18, 2019
Photo by Lucas Andión.

In my last posts we introduced the React Hooks and talked a little about managing the state with the state hooks (useState and useReducer). In this post we’ll cover the Effect Hook useEffect.

The Effect Hook lets you perform side effects in function components. Some examples of “side effects” or just “effects” can be data fetching, manually changing the DOM or setting up a subscription.

With the useEffect Hook we can tell React that after every render, the callback passed to this useEffect function as its first parameter (“effect”) should be called. React will remember this callback and call it later after performing the DOM updates.

useEffect(() => {
// Here the effect
});

Below is an example of an app with an input that changes the document title using Hooks:

Before Hooks, we only could manage this effects within the lifecycle methods of class components: componentDidMount, componentDidUpdate and componentWillUnmount. The logic of an effect ended up being spread out throughout the different lifecycle methods.

The example of the previous app implemented without Hooks:

We could extract the logic of updating the document title from the component state, but still we’ll have to call the updater function from different lifecycle methods.

When does useEffect run?

By default, it runs after every render but we can customize it with the second param of the useEffect function. As a second argument, the useEffect function accepts an array that allow us to tell React when we want our effect to be called.

After a render and before calling an effect, React will compare the array of values defined in the second parameter of the effect with the array defined in the same effect from the previous render. React will only call the effect when any value of the array has changed since the previous render.

In the previous example, we don’t need to update the document title (our effect) after every render but only when the state variable name has changed its value since the previous render. That’s why we pass an array with the value of name as the second parameter:

The same way, if we only want our effect to be called only after the first render, we have to pass an empty array [] (which never changes) as second parameter.

How do effects run?

Unlike componentDidMount and componentDidUpdate, effects scheduled with useEffect don’t block the browser from updating the screen. If you need your effect to be happen synchronously, you can use the Hook useLayoutEffect which has the same API as useEffect.

Effects with cleanup

There are some effects that require a cleanup to avoid memory leaks like subscriptions to external sources.

This is how we do the subscription of a component to an external source without Hooks:

And below the same example using Hooks:

As long as we only want our effect (subscribe to resizes) to be called once, we pass an empty array as the second parameter of the function useEffect.

An effect can optionally return a function (the cleanup function) that React will call when the component unmounts and before running the effect next time. In the example, our effect returns a function that unsubscribes it from the window resize events.

Example with multiple effects

It’s always a good idea to use multiple effects to separate concerns. Below is an example of a component that is subscribed to window resizes (we do this with the first effect) and shows the type of screen we’re managing depending on its width (second effect).

Summing up

React useEffect Hook allows you to manage side effects with no need of class components, and to extract and reuse the logic of an effect from a component. Before using it, it’s important to know the key points we covered in this post:

  • When and how does React perform the effects.
  • How to customize when an effect should be called.
  • How to cleanup the effects when unmounting the component.

--

--