novato en Javascript y React, tratando de aprender mi camino a través de React mediante la creación de pequeños proyectos. Estoy trabajando en un temporizador de cuenta regresiva en este momento, y me pregunto si hay una mejor manera de manejar la lógica de pausa/detención.
En este momento, estoy llamando a setInterval() cuando mi componente ya no está en estado "Paused" !paused paused, y devuelvo una función cleanup() para borrar el intervalo. Cuando lo registré en la consola, solo borró el intervalo en pausa/inicio.
Sin embargo, quiero agregar funcionalidad para detener automáticamente el temporizador una vez que llega a cero, lo que requiere agregar el estado de duration como una segunda dependencia. Cuando registré esto en la consola, me di cuenta de que mi setDuration y clearInterval ahora se estaban ejecutando en cada intervalo, en lugar de solo en la pausa/inicio (parece que está llamando a setInterval() en cada "tick" ahora).
Mi pregunta es: ¿es esto un problema? ¿Y hay una mejor manera de hacer esto?
function Timer(props) { const [duration, setDuration] = useState(10); const [paused, setPaused] = useState(true); useEffect(() => { let timerId; if (!paused) { timerId = setInterval(() => { setDuration(prev => prev - 1); }, 1000); // console.log(timerId); } if (duration === 0) { // console.log(`Time's up`); clearInterval(timerId); } return function cleanup() { // console.log(`Clearing ${timerId}`); clearInterval(timerId); }; }, [paused, duration]); const handleClick = (e) => { !paused ? setPaused(true) : setPaused(false); }; return ( <> <h3>{duration}</h3> <Button paused={paused} onClick={handleClick} /> </> ); }En su código, la duration cambia en cada intervalo y, debido a que se pasa como un parámetro en la matriz de dependencia, activa useEffect en cada intervalo, lo que hace que setDuration y clearInterval se ejecuten en cada intervalo.
puede usar el operador ternario para verificar si la duración es menor que cero, luego puede establecer automáticamente la duración en cero usando setDuration(0)
function Timer(props) { const [duration, setDuration] = useState(10); const [paused, setPaused] = useState(true); useEffect(() => { let timerId; if (!paused) { timerId = setInterval(() => { setDuration((prev) => prev - 1); }, 1000); console.log(timerId); } return function cleanup() { console.log(`Clearing ${timerId}`); clearInterval(timerId); }; }, [paused]); const handleClick = (e) => { !paused ? setPaused(true) : setPaused(false); }; return ( <> {duration >= 0 ? <h3>{duration}</h3> : setDuration(0)} <button paused={paused} onClick={handleClick} /> </> ); }Juega con el código aquí