Today I was writing a test and encountered the following error message while in my test runner:
console.error
Warning: 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 a useEffect cleanup function.
The code I was testing looked like this:
React.useEffect(() => {
dispatch({ type: "LOADING" });
axios
.get(`/api/v1/posts`)
.then((res) => {
dispatch({ type: "SUCCESS", payload: res.data });
})
.catch((error) => {
dispatch({ type: "ERROR", error });
});
}, []);
The problem is that my tests were running too quickly and causing the component to unmount by the time dispatch
was getting called. The easiest way to fix this issue is to set a mounted
variable that is updated when this component is unmounted:
React.useEffect(() => {
// successful mount
let mounted = true;
dispatch({ type: "LOADING" });
axios
.get(`/api/v1/posts`)
.then((res) => {
// avoids calling this when we've unmounted
if (mounted) {
dispatch({ type: "SUCCESS", payload: res.data });
}
})
.catch((error) => {
// avoids calling this when we've unmounted
if (mounted) {
dispatch({ type: "ERROR", error });
}
});
// called on unmount
return () => (mounted = false);
}, []);