If you use a useEffect hook in React to fetch some data from a server, you should make sure to cancel this request when the component gets unmounted.
To be honest, I am quite guilty of a fire-and-forget mindset when it comes to requests. But hey, there is always room to improve. That's why I hope to remember this once I wrote it down here.
Let's assume a useEffect usage like this:
useEffect(() => {
const doRequest = async () => {
const result = await fetch('...')
return await result.json()
}
const data = doRequest()
.catch(err => console.error(err))
[...]
}, [])
Now imagine the component gets mounted, but the user - impatient as they usually are - switches to a different page before the request had a chance to finish. No problem. The request finishes in the background, and nothing really happens with the result afterwards. So - no reason to worry, right?
Most of the time, yes. Except when you want to free the resource to make space for other requests. And let's be honest: You want to free all unneeded resources as fast as possible. Always.
So let's make use of a little helper called the AbortController
to make sure the request gets cancelled when the component is unmounted:
useEffect(() => {
const myAbortController = new AbortController()
const signal = myAbortController.signal
const doRequest = async () => {
const result = await fetch('...', { signal })
return await result.json()
}
const data = doRequest()
.catch(err => console.error(err))
[...]
return () => {
myAbortController.abort()
}
}, [])
And the same works also with axios requests.
Alright, I have no excuse to forget about this anymore. Let's try to be resourceful in a time when simple websites are getting bigger and bigger (yes, I am guilty of this as well).