La mayoría de las respuestas que encontré aquí fueron usar clearInterval() dentro de una declaración de devolución en useEffect(). Pero, aún por algunas razones, sigue ejecutándose.
También recibo la siguiente advertencia en los registros: -
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)
adjuntando el código de Referencia.
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); };```
No está pasando ningún deps a useEffect
, por lo que las funciones de efecto nunca se actualizan, y en la versión de clearServices
a la que llama, connectionInterval
y friends siguen siendo null
. Ver la nota aquí .
En general, me acercaría a setInterval
así:
useEffect(() => { const intervalFn = () => { console.log('interval fired') } const intervalId = setInterval(intervalFn, 1000) return () => { clearInterval(intervalId) } }, [])
(Esta versión realmente no tiene dependencias, porque todo se captura dentro de useEffect. pero en la práctica probablemente tenga algunas).
Tuve este problema hace un par de semanas y lo que hice para detenerlo fue establecer un nuevo estado después de borrar el intervalo .
Por ejemplo. Estaba tratando de construir una cuenta regresiva que corriera de 30 a 0 y se detuviera en 0. Esto es lo que hice
const [timeRemaining, setTimeRemaining] = useState(30); useEffect(() => { let timeLeft = timeRemaining; let interval = setInterval(() => { if (timeLeft === 0) { clearInterval(interval); setTimeRemaining(0); } else { setTimeRemaining((timeLeft -= 1)); } }, 1000); }, [timeRemaining]);
Establecer el estado en 0 después de borrar el intervalo era la única forma de detener el temporizador de cuenta regresiva en 0
En useEffect, debe declarar las dependencias en la matriz después de la función de devolución de llamada. En el código anterior, startServices es una dependencia porque se declara fuera de useEffect.
https://reactjs.org/docs/hooks-reference.html#useeffect
Puede obtener información sobre useEffect en el enlace.