I'm working on this project which uses setInterval and I'm having a little trouble understanding how setInterval works. The problem I'm having is that the each time I call setInterval the function seems to stack on top of each other resulting in the object appearing multiple times rapidly. I'm not sure what I'm doing wrong in this case. Can someone please help me out thanks.
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>
</>
)
It's because the timer
value isn't saved across renders so you can't cancel it.
var timer = null // <-- no
const [timer, setTimer] = useState(null) // <-- yes
...
// later in useEffect() and resetSquare()
// save the timer using setTimer(timer)
Reason for that is elsewhere: your component (and/or and of its parent) is recreated. There are just few reasons in general but it's hard to point a specific line of code without debugging:
key
prop is providedAnother root cause: your useEffect
does not have cleanup. While it should. And even without first reason, you would not have multiple concurrent timers but you still would have timer that would not stop when you're navigating away.
useEffect(()=>{
timer = setInterval(moveSquare, 2000)
return () => clearInterval(timer);
},[])
More on cleanup in official docs:https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.