Traté de crear una aplicación de temporizador simple con ReactJS y encontré el siguiente código en Internet.
¿La función que pasamos a useEffect se ejecutará con el cambio de dependencia o se recreará con cada cambio de dependencia y luego se ejecutará?
También registro en la consola la función de retorno de useEffect y se ejecuta con cada renderizado. ¿Se ejecuta solo cuando el componente se desmonta? o con cada render?
import { useEffect, useState } from "react"; const App = () => { const [isActive, setIsActive] = React.useState(false); const [isPaused, setIsPaused] = React.useState(true); const [time, setTime] = React.useState(0); React.useEffect(() => { let interval = null; if (isActive && isPaused === false) { interval = setInterval(() => { setTime((time) => time + 10); }, 10); } else { clearInterval(interval); } return () => { console.log("cleanup"); clearInterval(interval); }; }, [isActive, isPaused]); const handleStart = () => { setIsActive(true); setIsPaused(false); }; const handlePauseResume = () => { setIsPaused(!isPaused); }; const handleReset = () => { setIsActive(false); setTime(0); }; return ( <div className="stop-watch"> {time} <button onClick={handleStart}>start</button> <button onClick={handlePauseResume}>pause</button> <button onClick={handleReset}>clear</button> </div> ); }; export default App;El código dentro del useEffect se ejecutará cada vez que se cambie un valor de dependencia. En su caso, cada vez que isActive o isPaused cambia de estado.
Esto significa que se perderá la referencia al intervalo, ya que se redefine la variable de interval .
Para mantener una referencia constante, use el useRef para que la referencia persista durante los cambios de estado.
const App = () => { const [isActive, setIsActive] = useState(false); const [isPaused, setIsPaused] = useState(true); const [time, setTime] = useState(0); const interval = useRef(null) useEffect(() => { if (isActive && !isPaused) { interval.current = setInterval(() => { setTime((time) => time + 10); }, 10); } else { clearInterval(interval.current); interval.current = null; } return () => { clearInterval(interval.current); }; }, [isActive, isPaused]) ... }