setInterval() keeps running even after clearing it using clearInterval()
Most of the answers I found here was to use clearInterval() inside a return statement in a useEffect(). But, still for some reasons it keeps executing.
I'm also getting the following warning in the logs :-
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.
in StartTest (at SceneView.tsx:126)
attaching the code for Reference.
const [connectionInterval, setConnectionInterval] = useState(null);
const [batteryInterval, setBatteryInterval] = useState(null);
const [heartRateInterval, setHeartRateInterval] = useState(null);
useEffect(() => {
startServices();
return () => {
clearServices();
};
}, []);
const startServices= () => {
let ctnInt = setInterval(() => checkConnection(), 5000);
setConnectionInterval(ctnInt);
let btryInt = setInterval(
() =>
Battery(value => {
setBattery(value);
}),
900000,
);
setBatteryInterval(btryInt);
let hrRtInt = setInterval(
() =>
HeartRate(
hr => {
if (finish) {
clearInterval(heartRateInterval);
}
let rate = Math.round(hr);
setHeartRate(rate);
},
onError => {
console.log('API ERROR');
},
),
3000,
);
setHeartRateInterval(hrRtInt);
};
const clearServices = () => {
clearInterval(connectionInterval);
clearInterval(batteryInterval);
clearInterval(heartRateInterval);
};```
Solution 1:
You're not passing any deps to useEffect
, so the effect functions never update, and in the version of clearServices
that you call, connectionInterval
and friends are all still null
. See the note here.
In general I would approach setInterval
like this:
useEffect(() => {
const intervalFn = () => {
console.log('interval fired')
}
const intervalId = setInterval(intervalFn, 1000)
return () => {
clearInterval(intervalId)
}
}, [])
(this version really has no deps, because everything is captured inside useEffect. but in practice you would probably have some.)