Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
January 8, 2022 09:58 am GMT

Memory Leaks, How to avoid them in a React App.

What is a memory leak?

According to Wikipedia, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory that is no longer needed is not released. A memory leak may also happen when an object is stored in memory but cannot be accessed by the running code.

Simply put, a memory leak is said to occur whenever inaccessible or unreferenced data exists in memory. Nowadays, many modern programming languages have techniques for clearing out data that is no longer needed, garbage collection, but it turns out there are other not-so-popular errors which can expose your React app to memory leaks and, to a great extent, reduce the performance of your app.

Let's look at some causes of memory leaks.

Causes of Memory Leaks in a React Application

memory leak.PNG

Memory leaks in React applications are primarily a result of not cancelling subscriptions made when a component was mounted before the component gets unmounted. These subscriptions could be a DOM Event listener, a WebSocket subscription, or even a request to an API.

The first two are not too much of a challenge, as we can easily remove an event listener or unsubscribe from the WebSocket before the component gets unmounted. But the last one might require a little bit of extra work.

A typical React workflow

import { useState, useEffect } from 'react';import { Link } from 'react-router-dom';import axios from 'axios';const MyCompany = function() {    const [ company, setCompany ] = useState(null);    useEffect(() => {        (async () {             const { data } = await axios.get(                 'https://random-data-api.com/api/company/random_company'             );             setCompany(data);        })();    }, []);    return (        <>            <pre>{JSON.stringify(company, null, 3)}</pre>            <Link to = '/anotherpage'>Another Interesting Page</Link>        </>    )}

In the code snippet above, we have a simple component MyCompany which when mounted, makes a request to get a random company and sets value of company state to the value gotten from the API.

The Problem

Assuming our user has a very slow internet connection and then decides to leave the current page for another interesting page, the request would have already been made and our browser would be expecting a response, which when received, would lead us to call setState on a component that's no longer mounted.

Aside from setting state, we would now have unimportant data in our app with no means of accessing them. This process is repeated multiple times while the user uses the app, filling up useful memory with useless and inaccessible data and leading to serious performance issues.

We've seen the problems and I believe you understand, now let's look at how to solve this problem.

The Way Forward: AbortControllers

Having understood the problem, what we'd do to salvage the situation is cancel the request the moment our component unmounts, ensuring we don't get any data from the API.

So, how do we cancel requests? AbortControllers

According to MDN, the AbortController represents a controller object that allows you to abort one or more Web requests as and when desired. That's quite explanatory!!

AbortControllers are created with the new AbortController() syntax, initializing an instance of the AbortController class. Every AbortController object has a read-only signal property which is passed into requests, and an abort() method which is whenever you want to cancel a request.

Now using AbortControllers, our code should look like this:

import { useState, useEffect } from 'react';import { Link } from 'react-router-dom';import axios from 'axios';const MyCompany = function() {    const [ company, setCompany ] = useState(null);    useEffect(() => {         let abortController;        (async () {             abortController = new AbortController();             let signal = abortController.signal;                 // the signal is passed into the request(s) we want to abort using this controller             const { data } = await axios.get(                 'https://random-data-api.com/api/company/random_company',                 { signal: signal }             );             setCompany(data);        })();        return () => abortController.abort();    }, []);    return (        <>            <pre>{JSON.stringify(company, null, 3)}</pre>            <Link to = '/anotherpage'>Another Interesting Page</Link>        </>    )}

Now, when our user navigates to a new page, our AbortController cancels the request and we don't have to worry about having data leaks.

NOTE: Calling abortController.abort() after the request has been completed doesn't throw any errors. The abortController simply does not take any action on an already complete request.

Using AbortControllers in your web apps can help improve performance and prevent memory leaks, so it's something you should actually use.

Thanks for reading


Original Link: https://dev.to/jeremiahjacinth13/memory-leaks-how-to-avoid-them-in-a-react-app-1g5e

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To