Understanding React useEffect cleanup function

Anom Warbhuvan
8 min read | Published on : May 05, 2023
Last Updated on : May 27, 2024





Table of Contents

We must first have an understanding of side effects and the useEffect hook in order to comprehend the useEffect clean method.One of the biggest challenges us developers have is controlling side effects in our programmes. These difficulties may arise when modifying your website, configuring event listeners, or retrieving data from an API. Although these side effects can improve our application's functionality, if they are not properly controlled, they can also cause errors and negatively impact performance.

To handle these side effects efficiently, one can use the useEffect hook in React. It will allow you to define what should happen when a component mounts or updates. In our useEffect hook guide, you will learn more about how to use this hook effectively.

Every time you create a side effect in useEffect, you would need to use the useEffect cleanup function. Now, let’s dive into React’s useEffect cleanup function and how we can utilize it to manage side effects easily.

What is useEffect cleanup function in React?

The useEffect cleanup function is invoked when an element that makes use of the useEffect hook is taken from the screen. It is in charge of tidying up any unintended consequences that damage the code. Thus, before the component is unmounted, it makes sure that everything is in working order. The useEffect cleanup function is called when a component that uses the useEffect hook unmounts. Its job is to tidy up any unintended consequences that might affect the code.

Why do we often need a cleanup in React?

When working with React, it's usual to create additional actions like fetching information, setting up countdowns, or attaching event listeners. These side effects can create memory leaks, cause bugs, or make the app slower. By cleaning up these side effects, we can avoid these problems.

There are side effects which stay active even after a component unmounts. This can result in problems  such as slower performance, errors, and issues that we did not expect. To sum up, the useEffect cleanup function is crucial in managing side effects in React components lifecycle. Since you are here, I think you would also like to explore useEffect Hook for React Lifecycle, to understand how to manage side effects in functional components.

When is the useEffect cleanup function called?

useEffect cleanup function can takes place in two incidents:

  1. When a component using the useEffect hook unmounts.
  2. When the dependency array in the useEffect hook changes as it triggers a re-render of the component.

It is used to tidy up any unwanted effects that were created during the component's lifespan, and we can also use it to perform additional cleanup tasks.

Take React debugging to the next level, with AI assistance. Join Zipy!

Get Started for free

Cleaning up with useEffect function

You can choose to return a cleaning function when using the useEffect hook. Resources and effects created in the hook are cleaned up using this cleanup function.When obtaining data from an API, configuring event listeners, or establishing intervals or timeouts, you can eliminate side effects. Let's discuss each of these adverse effects separately.

Canceling a fetch request

Generally, you would want to stop a request whenever you obtain any data from an API in your component. particularly if the element is eliminated prior to the request's completion. This might occur if the user closes the browser or switches to another tab. If not, the fetch request will continue to run in the background, using resources and possibly resulting in problems for our application.

When we make a fetch request with fetch(), we can cancel it by calling the AbortController method. We can use this method in the cleanup function to avoid memory leaks. This is a built-in Web API that allows us to signal to a fetch request that we want to cancel it.

Using the cleanup function to cancel a fetch request in a React component:

    
// Importing hooks from the React library import { useEffect, useState } from 'react'; // Defining a functional component function MyComponent() { // Initializing a state variabl const [data, setData] = useState(null); // Defining a side effect to fetch data from an API useEffect(() => { // Create an instance of the AbortController API to abort the fetch request const controller = new AbortController(); // Define an asynchronous function to fetch data from the API const fetchData = async () => { try { // Make a GET request to the API and pass the AbortSignal of the controller const response = await fetch('API', { signal: controller.signal }); // Parse the response body as JSON const json = await response.json(); // Set the state variable data and log errors setData(json); } catch (error) { console.error(error); } }; // Call the fetchData function to fetch data from the API fetchData(); return () => { controller.abort(); }; }, []); // Render the data if it is available, otherwise showing a loading message return ( <div> {data ? ( <div> <p>Title: {data.title}</p> <p>Status: {data.status ? 'Yes' : 'No'}</p> </div> ) : ( <p>Loading...</p> )} </div> ); }

Here, we create a new AbortController and pass its signal to the fetch request options. This allows us to cancel the request if the component unmounts. We then return a cleanup function that calls the AbortController's abort method, which cancels the request. Keep in mind that you can replace the URL in the fetch method with any other API endpoint that returns JSON data.

By using the cleanup function in this way, we can promise that our fetch requests are properly canceled when our component unmounts.

Cleaning up timeouts

Before we discuss how to cleanup timeouts, let’s first understand what they are. In JavaScript, the setTimeout function is used to execute a piece of code after a specified amount of time has elapsed.

You may also use timeouts to postpone the execution of a certain piece of code. For instance, after a user completes an action, you might want to display a success message for a little while before concealing it.

Generally, you should clear a timeout that you have specified for a component if it unmounts before the timeout expires. In the event that the timeout is not cleared, our programme will behave strangely.

To clean up timeouts, we need to use the clearTimeout() method. This method allows us to cancel a timeout before it is executed. We can store the timeout ID in a variable and use it in the cleanup function to clear the timeout.

This code shows how you can use the cleanup function to clean up timeouts in a React component:

    
// import hooks from react import { useEffect, useState } from 'react'; // create a functional component function MyComponent() { const [counter, setCounter] = useState(0); // Using useEffect hook set counter useEffect(() => { const timeoutId = setTimeout(() => { setCounter(counter + 1); }, 3000); //update if dependency array changes again return () => { clearTimeout(timeoutId); }; }, [counter]); return ( <div> <p>Count: {counter}</p> </div> ); }

In the above code, we set a timeout that updates the count state variable after one second. We then return a cleanup function that calls the clearTimeout() method with the timeout ID, which cancels the timeout.

This will help us in ensuring that our timeouts are properly cleaned up before the component gets unmounted. It will also help us in preventing unexpected behavior or errors in our application and improve its overall stability.

Cleaning up intervals

In React's useEffect hook, an interval is a way to repeatedly execute a function after a certain period of time has elapsed. The setInterval function takes two arguments to create an interval, where function is the first argument and time interval is second argument.

The function passed to setInterval will be executed repeatedly at the specified interval until the component unmounts or the interval is cleared with the clearInterval function. It helps in polling a server for updates or periodically updating the UI.

You can refer this code on how to use the cleanup function to clean up intervals in a React component:

    
// import hooks from react import { useEffect, useState } from 'react'; // create a functional component function MyComponent() { const [counter, setCounter] = useState(0); // use the hook to update the counter by 1 useEffect(() => { const intervalNumber = setInterval(() => { setCounter(counter + 1); }, 3000); // if the dependency array changes, hook will run again return () => { clearInterval(intervalNumber); }; }, [counter]); return ( <div> <p>Count: {counter}</p> </div> ); }

In this example, we chose an interval that updates the count state variable every second. The interval is then cancelled by calling the clearInterval() method with the intervalNumber in the cleaning function that we subsequently return.

We can make sure that our intervals are correctly cleaned up when our component unmounts by utilizing the cleaning function in this manner.

Take React debugging to the next level, with AI assistance. Join Zipy!

Get Started for free

Cleaning up event listeners

When the component is removed from the screen, remove the event listener. This will prevent from memory leaks and potential bugs in your application.

The useEffect hook can be used to create an event listener and clean it up when the component is unmounted. To create an event listener using useEffect, you can use the addEventListener method on the window object inside the hook.

For example, let's say you want to create an event listener for the scroll event. You can use the following code:

    
// import the hooks from react import { useState, useEffect } from 'react'; function MyComponent() { const [scrollPosition, setScrollPosition] = useState(0); useEffect(() => { function scrollHandler() { // Update the state with the current scroll position setScrollPosition(window.pageYOffset); } // Add the event listener window.addEventListener('scroll', scrollHandler); // Remove the event listener on cleanup return () => { window.removeEventListener('scroll', scrollHandler); }; }, []); return ( <div> <p>Current scroll position: {scrollPosition}px</p> </div> ); }

In this code, the useEffect hook is used to add an event listener for the scroll event using window.addEventListener. The scrollHandler function is called when the event is triggered.

The second argument to useEffect is an empty array, which means that the hook will only run once, when the component is mounted. This ensures that the event listener is only added once.

The return statement inside the hook is used to clean up the event listener. When the component is unmounted, the function passed to return is called, which removes the event listener using window.removeEventListener.

By using useEffect to create and clean up event listeners, you can ensure that your React application is efficient and bug-free.

Cleaning up WebSockets

When working with WebSocket it is crucial to close the connection before a component unmounts in React application. By doing this, your application's possible flaws and memory leaks are avoided.

When a component is mounted, a WebSocket connection may be established and cleaned up using the useEffect hook. Use the WebSocket API within the hook to establish a WebSocket connection using useEffect.

Now if you plan to connect useWebSocket, you can refer to the code, I have shared here:

    
// import hook from react import { useEffect } from 'react'; // create a functional component function MyComponent() { useEffect(() => { const socket = new WebSocket('ws://localhost:3000'); socket.addEventListener('open', openHandle); socket.addEventListener('message', messageHandle); socket.addEventListener('close', closeHandle); // Clean up the WebSocket connection return () => { socket.removeEventListener('open', openHandle); socket.removeEventListener('message', messageHandle); socket.removeEventListener('close', closeHandle); socket.close(); }; }, []); function handleOpen() { console.log('WebSocket connection opened'); } function handleMessage(event) { console.log('Received data from server:', event.data); } function handleClose(event) { console.log('WebSocket connection closed with code:', event.code); } return ( <div> {/* Your component code here */} </div> ); }

Using the WebSocket API, a WebSocket connection is established in this code using the useEffect hook. The openHandle, messageHandle, and closeHandle functions are responsible for handling events during the communication between the client and server. The openHandle function will successfully connect with the server, whereas the messageHandle function is triggered upon receiving data by the client. Meanwhile, the closeHandle function is invoked upon closing the connection to the server.

The empty array sent as the second parameter to useEffect indicates that the hook should only be used once, when mounting the component. The hook's return clause is used to close the WebSocket connection. When the part of the program related to this feature is no longer in use, the supplied function is executed. This function removes the event listeners using socket.removeEventListener and ends the connection to the server using socket.close.

Using this cleanup function, we can perform critical tasks immediately after the component unmounts.

Take React debugging to the next level, with AI assistance. Join Zipy!

Get Started for free

Conclusion

Understanding the useEffect cleanup function is crucial for properly managing your React components side effects. However, useEffect is just one part of React's complex lifecycle, and it's important to have a solid understanding of the whole picture to create robust and performant applications. We highly recommend you to check out our other blog posts on related topics, such as useEffect Hook for React Lifecycle, useEffect hook guide, and useEffect dependency array.

By mastering these concepts, you can make the most of React's robust programming style and create productive, maintainable, and simple-to-reason apps. We hope this article will be helpful in your journey towards becoming a React expert.

Till then. Happy Coding!

Wanna try Zipy?

Zipy provides you with full customer visibility without multiple back and forths between Customers, Customer Support and your Engineering teams.

The unified digital experience platform to drive growth with Product Analytics, Error Tracking, and Session Replay in one.

product hunt logo
G2 logoGDPR certificationSOC 2 Type 2
Zipy is GDPR and SOC2 Type II Compliant
© 2024 Zipy Inc. | All rights reserved
with
by folks just like you