首页 > 解决方案 > 我找不到在 React 中暂停倒数计时器的方法(清除间隔似乎不起作用)

问题描述

我正试图弄脏我的手来建造一个番茄钟。我现在正试图暂停计时器,但我很难做到这一点。这是主 App 组件中的构造函数:

this.state ={
      breakValue: 5,
      sessionValue: 25,
      time: 25*60*1000,
      isRunning: false
    }

现在,这个功能正在滴答作响:

countDown = (timeLeft ) =>{

  this.setState({

    time : timeLeft-1000,


  })

我已经通过道具将此功能传递给控件组件:

countDown={this.countDown}

在 Controls 组件中,我已经像这样处理了该功能:

handleStart = () =>{
 this.props.countDown(this.props.time);
    }

我为 SetInterval 做了一个单独的函数:



interval = () =>{
   setInterval(this.handleStart,1000)


} 

最后,我将最终功能附加到 onClick 按钮:

handleSetInterval= () =>{
    this.interval();

} 

现在计时器正在滴答作响,倒计时正在工作。但是如何随时暂停这个计数器呢?我有另一个带有暂停功能的按钮,我尝试用 clearInterval 编写一个函数,但它不起作用。我应该使用布尔逻辑来启动/停止,还是可以处理 Main App 组件内的 clearInterval?我完全迷路了。谢谢你们的任何回答。

标签: javascriptreactjs

解决方案


请记住,这不会是一个超级准确的计时器,因为 setIntreval 进入队列,因此它的回调不会在 1000 毫秒时立即调用(这只是意味着它将每 1000 毫秒排队一次)

工作片段(根据您的规范,请查看第二个示例以获得更好的实践):

class Controls extends React.Component{
    state={
        myInterval : null
    }
    startTimer = () => {
        this.setState({myInterval : setInterval(this.props.countDown,1000)})
    }
    stopTimer = () => {
        clearInterval(this.state.myInterval)
    }
    render(){
        return(
            <div>
                <button onClick={this.startTimer}>Start</button>
                <button onClick={this.stopTimer}>Stop</button>
                {this.props.time}
            </div>
        )
    }
}


class App extends React.Component{
    state ={
        time: 25*60*1000
    }
    countDown = () => {
        this.setState({
            time : this.state.time-1000,
        })
    }

    render(){
        return <Controls time={this.state.time} countDown={this.countDown}/>
    }
}





ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<div id='react'></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

更好/最佳实践是将与计数器相关的所有内容移动到您的计数器组件中

如果您需要在应用程序的其他地方访问 this.state.time ,请考虑使用 useContext 或 Redux (根据 React 团队对频繁更改的状态的应用程序级别管理尝试使用 Redux 而不是 useContext ,这里就是这种情况)。

应用程序组件级别的 setState() 可能会在每次更新时重新渲染应用程序中的所有内容(在这种情况下大约每 1000 毫秒)

更好的例子:

class Controls extends React.Component{
    state={
        myInterval : null,
        time: 25*60*1000
    }
    countDown = () => {
        this.setState({
            time : this.state.time-1000,
        })
    }
    startTimer = () => {
        this.setState({myInterval : setInterval(this.countDown,1000)})
    }
    stopTimer = () => {
        clearInterval(this.state.myInterval)
    }
    render(){
        return(
            <div>
                <button onClick={this.startTimer}>Start</button>
                <button onClick={this.stopTimer}>Stop</button>
                {this.state.time}
            </div>
        )
    }
}


class App extends React.Component{
    render(){
        return <Controls/>
    }
}





ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<div id='react'></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


推荐阅读