How to Cleanup Side Effects in React

Avoid memory leaks in your react application.

ReactOne
3 min readNov 17, 2021

In react, we use useEffect when we need to do something after a component renders or when it needs to cause side effects. A side effect may be fetching data from a remote server, reading from or writing to local storage, setting event listeners, or setting up a subscription.

useEffect() allows us to manage component life-cycles within functional components. The useEffect() hook can be thought of as a combination of componentDidMount, componentDidUpdate, and componentWillUnmount combined.

However, sometimes we may encounter challenges at the junction of the component lifecycle and the side-effect lifecycle (start, in progress, complete).

When a side-effect completes, it attempts to update the state of a component that has already been unmounted. As a result, a React warning appears:

Warning: Can’t perform a React state update on an unmounted component.
Memory leak warning

In this post, we’ll discuss when the above warning appears and how to correctly clean side effects in React to avoid memory leaks.

1 — The issue

First, let’s reproduce the issue in an example. The example shows information about either users or a plain hello world text. The users' list is loaded using a fetch request.

App component
Hello component
Users component

Before the users’ fetching completes, click the display hello message button, and a warning message appears in the console.

The reason for this warning is that the component has already been unmounted, yet the side-effect completes and attempts to update the state of the unmounted component.

The solution is to cancel any side effect if the component unmounts, let’s see how to do that in the next section.

2 — Clean Up

Fortunately, useEffect(callback, dependencies) allows us to easily clean up side-effects. When the callback function returns a function, React will use that as a cleanup.

useEffect(() => {

// the side effect takes place here.
return () => {
// the cleanup function
}
// dependencies array}, [])

2 — 1 Clean up fetch requests

First, we create a controller that allows us to abort DOM requests, then we connect the controller with the fetch request. And finally, the cleanup function t aborts the request in case if the component umounts.

Aborts the request when the component umounts

2 — 2 Clean up on prop or state update

There might be cases when we want to abort a fetch request when the side-effect depends on a prop or a state value .and as I mentioned before useeffect() hook can handle these cases. For example, consider the following component <User> that fetches a request to load the details of a specific employee based on the id provided in the props.

Clean up on prop or state update

2 — 3 Clean up timers

When using timer functions, we can clear them on unmount by using the special clearTimeout(timerId) function.

For example, consider a counter that automatically increments each second.

Clean up timers when the component unmounts.

2 — 4 Clean up subscriptions

We might want to set up a subscription to some external data source. In that case, it is important to clean up when the component unmounts. For example web sockets.

Clean up web sockets connection when the component unmounts.

3 — CONCLUSION

Some effects might require cleanup to avoid memory leaks. useEffect() allows us to perform different kinds of side effects after a component renders, and then clean them up depending on their kind.

For more cool content and projects just like this one please Follow us and consider checking our Github Repository:

--

--

ReactOne

We are a small team of React Native and AWS experts