【问题标题】:React functional component: clearInterval() does not clear my intervalReact 功能组件:clearInterval() 没有清除我的间隔
【发布时间】:2019-03-27 14:48:59
【问题描述】:

我正在构建一个简单的计时器应用程序。当用户点击播放时,handlePlayPause 函数被调用。我创建了一个 isRunning 布尔值来检查计时器是否已经在运行。如果不是,则计时器将启动(这第一部分有效),而如果是,则调用 pauseTimer 函数。最后一个函数将isRunning 切换回 false 并且应该清除间隔。但是,间隔不会被清除。你能看到我做错了什么吗?

感谢您的帮助!

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

【问题讨论】:

  • 如果您提供一个简洁的可运行示例会很好
  • 尽可能向我们展示clearInterval 方法
  • @tomrlh clearInterval 是浏览器 API 的一部分,与 setInterval 相同。 see more details

标签: javascript reactjs react-hooks


【解决方案1】:

我认为问题在于您如何存储间隔 ID。当使用函数组件并且我们想要存储“实例”变量时,我们可以使用useRef 钩子。

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

react docs 上有一个与您的用例类似的示例

【讨论】:

  • 就是这样,我将进一步研究 useRef。非常感谢。
猜你喜欢
  • 2023-02-20
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
  • 2022-06-11
  • 2020-08-09
  • 2021-07-05
相关资源
最近更新 更多