Avoid memory leak in your React.js apps
What is memory leak?
In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory which 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.
-Wikipedia
So, you just added a feature, styled it nicely and visuals match with your design. I know its a great feeling but are you sure not forgetting something? have you thought about corner cases, responsive views for tablet and mobile, unit tests ? Did you review your own code?
What about cancelling network calls for which response didn't arrive when a component existed for it but it only arrived after component no longer existed?
If you have been writing react.js apps and integrating a lot of APIs to it across different views (a.k.a pages), there could be a memory leak if the user quickly navigates between pages when the network is too slow. Fortunately modern browsers are too smart and will not ordinarily crash but why let the problem persist if the solution is simple.
During development, we are mostly on a high-speed network and we don't normally navigate between pages so fast so we rarely notice this React warning.
How do you know if your app has this problem and how do you replicate it?
slow down your network by selecting at least "Fast 3G" option from the Chrome developer tools, network option
let's say, when an app starts on the home page, it makes an API call and when user clicks on an item then it goes to the details page and makes another API call there.
go to home page, hit refresh button and before API call comes back with response, hit browser next button to go to details page (assuming you have this URL in browser history)
when API call comes back with response, you will see above React warning because now response has no where to go on screen as home page is unmounted.
How to fix this problem?
It is very simple to fix this problem. just cancel the request when a component unmounts. I fixed this problem in my project which uses Axios library for API calls.
In the functional component, before making axios request, just grab the cancelToken and save it using Refs like so:
const CancelToken = axios.CancelToken; const source = CancelToken.source(); const sourceRef = React.useRef(source)
Then in your useEffect, cancel the network request in a return function which will get called by React when a component unmounts.
Here is the sample code:
useEffect(() => {
const source = sourceRef.current
console.log(source.token)
if(state.results.length === 0 && state.searchPhrase.length === 0)
{
setMessage("")
setShowLoader(true)
const fetchData = async ()=> {
try{
const countries = await Apis.getCountries(source.token)
dispatch({type:'SET_COUNTRIES', payload:countries})
setShowLoader(false)
}catch(error)
{
if(axios.isCancel(error))
{
console.log("axios cancel")
}
setRedirectToError(true)
}
}
fetchData()
return () => {
console.log("unmount..")
setShowLoader(false)
source.cancel()
}
}
},[state.results, state.searchPhrase, dispatch])
If you are interested in the full code, here is the github link: Full Code @ Github
Now, try to replicate the same issue using above steps and you will find that React warning is no longer coming.
Happy days! You just made your app better.
Hey isn't useIsMounted hook does the same