mrc
mrc

Reputation: 71

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>
  )
}

Upvotes: 3

Views: 5142

Answers (1)

Sagiv b.g
Sagiv b.g

Reputation: 31024

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

Upvotes: 11

Related Questions