Reputation: 67
I want to have all of the setTimeOut cleared when the component is unmounted. Even though I have use clearTimeOut as a clean up function but the error still persis: "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"
useEffect(() => {
const timeOut = {timeout1: ()=>setTimeout(() => setProgress((preV) => preV + 15), [
550,
]),timeout2 : ()=> setTimeout(() => setMessage("All most done"), [500])}
timeOut.timeout1();
timeOut.timeout2();
return () => {
clearTimeout(timeOut.timeout1);
clearTimeout(timeOut.timeout2);
};
}, [progress,message]);
Does anyone know how to solve this issue? Any help would be appreciated!
Upvotes: 1
Views: 624
Reputation: 353
How about to use a local variable that keeps track of whether the component is mounted or not.
useEffect(() => {
let run = true;
const timeOut = {
timeout1: () => setTimeout(() => setProgress((preV) => preV + 15), [550]),
timeout2: () => setTimeout(() => setMessage('All most done'), [500]),
};
if (run) {
timeOut.timeout1();
timeOut.timeout2();
}
return () => {
clearTimeout(timeOut.timeout1);
clearTimeout(timeOut.timeout2);
run = false;
};
}, [progress, message]);
Upvotes: 0
Reputation: 281894
timeout1 isn't storing the returned value of setTimeout which is the timerId but its storing the reference of the function that executes timeout
You could write your code in a way that it executes the timeouts immediately using Immediately invoked functions
so that timeout1
and timeout2
have timerIds
useEffect(() => {
const timeOut = {
timeout1: (()=>setTimeout(() => setProgress((preV) => preV + 15), 550))(),
timeout2 : (()=> setTimeout(() => setMessage("All most done"), 500))()
}
return () => {
clearTimeout(timeOut.timeout1);
clearTimeout(timeOut.timeout2);
};
}, [progress,message]);
however you could simply run the timeouts without writing them as IIFE
useEffect(() => {
const timeOut = {
timeout1: setTimeout(() => setProgress((preV) => preV + 15), 550),
timeout2 : ()=> setTimeout(() => setMessage("All most done"), 500)
}
return () => {
clearTimeout(timeOut.timeout1);
clearTimeout(timeOut.timeout2);
};
}, [progress,message]);
Upvotes: 1