Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React functional component: clearInterval() does not clear my interval

I'm building a simple timer app. When the user clicks play the handlePlayPause function is called. I've created an isRunning boolean to check if the timer is already running. If it's not, the timer will start (this first part works), whilst if it is, the pauseTimer function is called. This last function switches isRunning back to false and should clear the interval. However, the interval does not get cleared. Can you see what i'm doing wrong?

Thank you for your help!

export default function App() {
  const [sessionLength, setSessionLength] = useState(25)
  const [breakLength, setBreakLength] = useState(5)
  const [timeLeft, setTimeLeft] = useState(25 * 60 * 1000)
  const [isRunning, setIsRunning] = useState(false)

  let intervalId = null

  let handlePlayPause = () => {
    if (!isRunning) {
      setTimeLeft(sessionLength * 60 * 1000)
      playTimer()
    } else if (isRunning) {
      pauseTimer()
    }
  }

  let playTimer = () => {
    setIsRunning(true)
    intervalId = setInterval(() => {
      setTimeLeft(timeLeft => timeLeft - 1000)
      parseToMinuteSeconds(timeLeft)
    }, 1000)
  }

  let pauseTimer = () => {
    setIsRunning(false)
    clearInterval(intervalId)
  }

  let resetAll = () => {
    setSessionLength(25)
    setBreakLength(5)
  }

  let parseToMinuteSeconds = timeInMilliseconds => {
    return //a string with the time in this format 00:00
  }

  return ( 
     <div className="App">
        <Background>
           <UpperMetalBand />
           <UpperPart />
           <LowerPart />
           <LowerMetalBand />
           <Wrapper>
              <Title>Pomodoro</Title>
              <Subtitle>TIMER</Subtitle>
              <PlayButton 
                  id="start_stop"
                  onClick = {handlePlayPause}
              >
                 <i className="fa fa-play" />
              </PlayButton>
              <Reload 
                 onClick={resetAll}
                 id="reset"
              >
                 <i className="fas fa-sync-alt" />
              </Reload>
              <Session 
                 setSessionLength={setSessionLength}
                 sessionLength={sessionLength}
              />
              <Break 
                 setBreakLength={setBreakLength}
                 breakLength={breakLength}
              />
              <span id="time-label">
                 <Timer id="time-left">00:00</Timer>
              </span>
           </Wrapper>
        </Background>
     </div>
  )
}
like image 606
mrc Avatar asked Aug 15 '26 11:08

mrc


1 Answers

I think the problem is with how you store the interval id. when using function components and we want to store "instance" variables we can use the useRef hook.

   let intervalId = useRef(null)
  
  let handlePlayPause = () => {
   
    if (!isRunning) {
      setTimeLeft(sessionLength * 60 * 1000)
      playTimer()
    } else if (isRunning) {
      pauseTimer()
    }
  }

  let playTimer = () => {
    setIsRunning(true)
    intervalId.current = setInterval(() => {
      console.log('interval')
      setTimeLeft(timeLeft => timeLeft - 1000)
      parseToMinuteSeconds(timeLeft)
    }, 1000)
  }

    
  let pauseTimer = () => {
    setIsRunning(false)
    clearInterval(intervalId.current)
  }

There is a similar example to your use case on the react docs

like image 199
Sagiv b.g Avatar answered Aug 17 '26 02:08

Sagiv b.g



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!