Memory Leaks in ReactJs
Memory leak can be understand like program engaging memory for unused data. Data is stored in memory but not used by and program.
React developer can understand by these given examples likes:
1. DOM Event Listener
Let's suppose we define any event handler on component mount but forgot to define remove event
listener
on component unmount. When component unmount this listener still present in memory but as unused handler.
So it is recommended to always define remove event listener on component unmount or clean up callback. see the below code sample for an idea.
const MyComponent = () => {
useEffect(() => {
const handleClick = () => {
//do something when we click
};
document.addEventListener('mousedown', handleClick);
return() => {
//Clean up callback function
//Always call on component unmount
document.removeEventListener('mousedown', handleClick);
};
}, []);
return ...
};
export default MyComponent;
2. API Request
Let's suppose we call any API on component mount but API response taking time , In between if we move on some other page, then our component will unmount but browser still busy with fetching response from the API.
After few second, if our browser received response and store the result in memory but that resultant data is useless because component is already unmounted.
this type of useless data occupying memory and may cause any serious performance issues.
Solution,
To avoid this type of issue, always cancel the API request before the component unmount.
"AbortControllers" is the solution. As per MDN, it allows us to abort the request at any point of execution. First we need to create an instance of AbortController like `new AbortController()`. This controller has a corresponding `signal` property which we can use to signal and abort asynchronous operation. We need to call `abortController.abort()` to trigger `signal` property, which will leading to the fetch operation being aborted.
This can be useful for handling situations where you want to cancel ongoing requests or timers when they are no longer needed.
see the below code sample for an idea.
import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
const MyOrganization = function() {
const [ org, setOrg ] = 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/organization/random_info',
{ signal: signal }
);
setOrg(data);
})();
return () => abortController.abort();
}, []);
return (
<>
<pre>{JSON.stringify(org, null, 3)}</pre>
<Link to = '/otherpage'>Other 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: Once API request is completed and then If we call `abortController.abort()` , it will not throw any error. In simple it will not trigger any action which will harm your program.
It is recommended, if you have this type of situation in your project. It helps to prevent memory leak and improve the app performance.
Comments