From: https://wareboss.com/react-hook-clean-up-useeffect/
Last article we learn about Asynchronous actions on useEffect and our correct usage (React Hook - Async funcion in useEffect).
Today we will see how to use the clean up function of useEffect React Hook.
When you update a state from an unmounted component, React will throw this error:
"Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method."
useEffect(() => {
//Do all the job, for example, subscribe a websocket channel
return function(){
//Unsubscribe websocket channel
};
}, []);
Prevent update on unmounted component:
Here you'll learn how to prevent this problem
useEffect(() => {
let isCancelled = false;
const runAsync = async () => {
try {
if (!isCancelled) {
// do the job
}
} catch (e) {
if (!isCancelled) {
throw e;
}
}
};
runAsync();
return () => {
isCancelled = true;
};
}, [...]);
Usage with setInterval/setTimeout:
This is a nice solution to abort setInterval/setTimeout:
useEffect(() => {
const interval = setInterval(() => {
console.log('Five Seconds!');
}, 5000);
return () => clearInterval(interval);
}, []);
Imagine this use case: you opened this component and then closed.
Withou clean up you will continues running the setInterval callback.
Usage with Firestore Realtime Database:
This is useful when using Firestore Realtime Database:
useEffect(() => {
//Subscribe: firebase channel
const cleanUp = firebase.firestore().collection('photos') .doc(id)
.onSnapshot( doc => {
setLoading(false);
setPhotos(doc)
}, err => { setError(err); }
);
return () => cleanUp(); //Unsubscribe
}, []);
If you forgot to clean your firestore subscription, you may receive unnecessary requests.
Usage with fetch + AbortController:
Cancel fecth with AbortController from fetch/es6:
useEffect(() => {
const abortController = new AbortController();
const fetchData = async () => {
try {
const ret = await fetch("/companies", { signal: abortController.signal });
const data = await ret.json();
// ...
}
catch(error) {
if (abortController.signal.aborted) {
// cancelled
}
else
throw error;
};
};
fetchData();
return () => abortController.abort();
}, [companies]);
Usage with axios request:
Here is how to cancel the request with axios.
useEffect(() => {
const source = axios.CancelToken.source();
const fetchData = async () => {
try {
const response = await Axios.get("/companies", {
cancelToken: source.token
});
// ...
} catch (error) {
if (Axios.isCancel(error)) {
//cancelled
} else {
throw error;
}
}
};
fetchData()
return () => {
source.cancel();
};
}, [companies]);
The useEffect function is the equivalent of componentDidMount in a React Class component.
The clean up function is the equivalent of componentWillUnmount in a React Class component.
Next article: React Class Component and React Function Component differences.
Bye bye!
Top comments (4)
Hi Igor, I'm Katie, one of the basic moderators here on DEV.
My unofficial title: DEV cheerleader π
I want to welcome you to the DEV community and let you know that you'll find lots of help and support here for all your coding needs.
Don't hesitate to ask questions.
It's great to see you are already contributing new posts!
Hello! Thank you, i appreciate you attention.
Bye bye!
Thank you for this awesome post!
super helpful post! thanks so much!
Some comments have been hidden by the post's author - find out more