¿Por qué mi variable de ID de setInterval global no está disponible para una función?
Estoy escribiendo una aplicación de temporizador simple y usando setInterval por primera vez. El proyecto está en react typescript y uso el hook useReducer para gestionar el estado.
El proyecto requiere dos temporizadores separados, sesión y descanso, lo cual puede explicar parte del código. El proyecto también requiere un botón para iniciar y detener el temporizador, por lo tanto, estoy usando una sola función.
He redactado mi reducer y types porque el problema, según entiendo, no los involucra, sino más bien un uso simple de setInterval que aún no entiendo.
Cuando se llama a la función startStopTimer por segunda vez, intervalID es indefinido, a pesar de que se declara globalmente.
const App = () => {
const [timerState, dispatch] = useReducer(timerStateReducer, initialTimerState
);
};
let intervalID: NodeJS.Timer;
const startStopTimer = () => {
let name: string = timerState.session.count !== 0 ? 'session' : 'break';
if (timerState[name].running) {
console.log('deteniendo temporizador' + intervalID);
//el reducer establece la variable booleana 'running' en false
dispatch({type: ActionKind.Stop, name: name});
clearInterval(intervalID);
} else {
//el reducer establece la variable booleana 'running' en true
dispatch({type: ActionKind.Start, name: name});
intervalID = setInterval(() => {
dispatch({type: ActionKind.Decrease, name: name});
}, 1000);
}
};
return (
//código JSX redactado
<button onclick="{startStopTimer}">Iniciar/Detener</button>
)
He intentado pasar onClick como una función de flecha (en lugar de una referencia, creo?) y se comporta de la misma manera. Intenté simplificar esto con useState, pero me encontré con otro conjunto de problemas con useState y setInterval, así que volví al hook useReducer.
¡Gracias!
davy.ai
Parece que el problema es que el
intervalID
no se está almacenando correctamente entre las llamadas a la función. Aunque se declara de forma global, se establece comoundefined
cuando se vuelve a llamar astartStopTimer
.Una posible solución es almacenar el
intervalID
en el estado utilizando el hookuseRef
, que persistirá entre las llamadas a la función. Así es como puedes modificar el código:Aquí, declaramos
intervalID
utilizandouseRef<nodejs.timer>()
que devuelve un objeto con una propiedad.current
. Este objeto es el mismo entre renders, por lo que podemos almacenar y acceder al valor deintervalID
a través de la propiedad.current
.Cuando se llama a
startStopTimer
por primera vez, establecemosintervalID.current
utilizandointervalID.current = setInterval(...)
. Cuando se llama de nuevo, podemos acceder al mismo valor deintervalID.current
.</nodejs.timer></nodejs.timer>