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!
[hidden by post author]