最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React functional component: clearInterval() does not clear my interval - Stack Overflow

programmeradmin1浏览0评论

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

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

Share Improve this question edited Mar 27, 2019 at 15:35 Sagiv b.g 31k10 gold badges72 silver badges104 bronze badges asked Mar 27, 2019 at 14:48 mrcmrc 711 silver badge7 bronze badges 3
  • would be nice if you provide a concise run-able example – Sagiv b.g Commented Mar 27, 2019 at 15:18
  • Show us the clearInterval method if possible – tomrlh Commented Mar 27, 2019 at 15:23
  • @tomrlh clearInterval is part of the browser API, same as setInterval. see more details – Sagiv b.g Commented Mar 27, 2019 at 15:36
Add a ment  | 

1 Answer 1

Reset to default 11

I think the problem is with how you store the interval id. when using function ponents 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

发布评论

评论列表(0)

  1. 暂无评论