Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

158
Views
SetInterval "Stacking" on top of each other

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>
    </>
)
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

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)
about 4 years ago · Juan Pablo Isaza Report

0

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:

  • Either conditional rendering (e.g. showing spinner during request and after render element with children again)
  • Or different key prop is provided
  • Or by mistake you put component declaration(function or class or wrap into HOC) inside of other component's render code and every time parent is rerendered, component's declaration becomes referentially different

Another 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

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!