Estoy trabajando en este proyecto que usa setInterval y tengo algunos problemas para entender cómo funciona setInterval. El problema que tengo es que cada vez que llamo a setInterval, la función parece apilarse una encima de la otra, lo que hace que el objeto aparezca varias veces rápidamente. No estoy seguro de lo que estoy haciendo mal en este caso. Alguien me puede ayudar gracias.
const [hit, setHit] = useState(0) const [count, setCount] = useState(0) var timer = null var funcCalls = 0 const hitSound = new Audio("/hit.wav") useEffect(()=>{ timer = setInterval(moveSquare, 2000) },[]) function handleHit(){ hitSound.play() setHit(hit+1) resetSquare() } function resetSquare(){ clearInterval(timer) moveSquare() timer = setInterval(moveSquare, 2000) } function moveSquare(){ const gameContainer = document.getElementById("game-container") const height = gameContainer.offsetHeight const width = gameContainer.offsetWidth const square = document.getElementById("square") square.style.top = (Math.random() * (height - 100)) + "px"; square.style.left = (Math.random() * (width - 100)) + "px"; } return ( <> <section className='game-section'> <div className='counter'> {hit} {count} </div> <div className='game-container' id = "game-container"> <div className="square" id = "square" onClick={handleHit}></div> </div> </section> </> )Es porque el valor del timer no se guarda en los renderizados, por lo que no puede cancelarlo.
var timer = null // <-- no const [timer, setTimer] = useState(null) // <-- yes ... // later in useEffect() and resetSquare() // save the timer using setTimer(timer)La razón de eso está en otra parte: su componente (y/o y de su padre) se recrea. En general, hay algunas razones, pero es difícil señalar una línea de código específica sin depurar:
key diferente Otra causa raíz: su useEffect no tiene limpieza. Mientras debería. E incluso sin una primera razón, no tendría múltiples temporizadores simultáneos, pero aún tendría un temporizador que no se detendría cuando esté navegando.
useEffect(()=>{ timer = setInterval(moveSquare, 2000) return () => clearInterval(timer); },[])Más información sobre limpieza en documentos oficiales:https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup