【问题标题】:Arrow function stored in State存储在 State 中的箭头函数
【发布时间】:2020-10-02 15:38:15
【问题描述】:

所以我有这个问题,我不知道这是一个错误的概念还是该概念的错误实施。 我在 freecodecamp.org 中做番茄钟,这迫使我在纯 js 和 React 组件中使用 setInterval() 函数。

在 Pomodoro 组件内部,每次它被挂载到 DOM 树中时,都应该运行 setInterval 检查状态并根据组件的状态进行计时。事实上,我可以看到状态变量发生了变化(感谢 React 调试工具),但间隔不起作用

componentdidmount 在将组件渲染到 DOM 树中后运行并检查 state.status,如果它为 true,则检查要运行的周期,是会话还是中断时钟。一个计时器结束后,另一个应该立即启动。

这个计时器或间隔存储在组件状态中,然后从 this.state.interval 状态中清除。


class Pomodoro extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
     session:1500,
     break:300,
     cycle:true,
     status:false,
     sessionClock:1500,
     breakClock:300,
     interval:0,
    }
 this.addSessionTime = this.addSessionTime.bind(this);
 this.decSessionTime = this.decSessionTime.bind(this);
this.addBreakTime = this.addBreakTime.bind(this);
 this.decBreakTime = this.decBreakTime.bind(this);
 this.pause = this.pause.bind(this);
 this.reset = this.reset.bind(this);
  }

/*Avoided all the other binded functions since they are just setStates*/


componentDidMount() {  

if (this.state.status) 
{


  if (this.state.cycle /* cycle true = session */) 


      { 
        this.setState({
          interval:(setInterval( ()=> {


      if (!this.state.status/*status true = clock running*/ ) {clearInterval(this.state.interval);}
      else 

        {/*begin session clock*/
          if (this.state.sessionClock > 1 /*check if is the last second*/)
          {
        this.setState({sessionClock: this.state.sessionClock - 1});
                      /*take away a second from sessionClock*/
          }

       else {this.setState({cycle:!this.state.cycle, sessionClock:this.state.session}) }
        }                  /*change cycle and restart sessionclock*/

                                                  }
    ,1000)
      )})}

else /*cycle off = break time*/

{

  this.setState({interval: setInterval(()=>{
if (!this.state.status) {clearInterval(this.state.interval)}
    else {
      /*begin break clock*/
          if (this.state.breakClock > 1) 
            {this.setState({breakClock:this.state.breakClock - 1})}
              else {this.setState({cycle:!this.state.cycle, breakClock:this.state.break})}        


          }

},1000)})

}
} 

else  { clearInterval(this.state.interval)}


}  





由于将 setInterval 保存到组件状态或其他原因导致时钟不工作?

编辑

添加了一个代码笔,以便您可以看到实时版本和状态变化

https://codepen.io/bigclown/pen/bGEpJZb

编辑二

删除了 componentdidmount 方法并将内容移至 pause() 方法,但现在两个时钟同时运行并且时钟运行速度比预期的快(可能是来自 react 中的异步状态更新的问题?)

【问题讨论】:

  • 那么“时钟不工作”究竟是什么意思?不算数吗?不显示?不是从工作转移到休息吗?
  • 不计算既不移动也不暂停播放
  • 存储对区间的引用很好,这就是你正在做的——你不是在存储箭头函数。不过,我觉得咖啡很难推理。
  • 感谢@DaveNewton 指出错误,“我觉得咖啡很难推理”是什么意思?
  • cDM 在安装时被调用一次。 “咖啡”是“代码”的自动更正。我看不懂你的代码。公平地说,我也看不懂你的咖啡,但这不太重要。代码倒转并不能说明它有多棒;)圈复杂度会扼杀理解。

标签: javascript reactjs


【解决方案1】:

我怀疑您的时钟同时运行并且计时器关闭的问题是由于在启动新计时器之前没有停止旧计时器。

您可能正在寻找的是componentDidUpdate 方法。此方法可让您将上一个状态与当前状态进行比较,并相应地进行更改。使用该方法,您可以检查我们何时从休息时间切换到会话时间,然后停止旧计时器以启动新计时器,如下所示:

  componentDidUpdate(prevProps, prevState) {
    // We need to check that the new state is different from the old state
    // if it is, stop the old timer, and kick off the new one
    if (prevState.cycle !== this.state.cycle) {
      clearInterval(this.state.interval);
      if (this.state.cycle) {
        // If the cycle switched to session, start the session timer
        this.startSession();
      } else {
        // If the cycle switched to break, start the break timer
        this.startBreak();
      }
    }
  }

这样,只要您的会话或休息计时器达到 0,您切换 this.state.cycle,您将始终启动新计时器。

查看我的新 codepen here 以获得完整功能的代码

【讨论】:

    【解决方案2】:

    问题在于您对componentDidMount 的使用。它在组件挂载时调用,这意味着它在用户与屏幕交互之前被调用。

    你的支票

    if (this.state.status) 
    

    永远不会是真的,因为您的状态将status 设置为假。 查看您的代码,我假设您的意思是 暂停按钮 将状态切换为 true,并且您认为 componentDidMount 中的代码会运行。


    您应该做的是将您的代码移动到pause() 函数中,因为这实际上是您的时钟的触发器。

    从那里你可以做类似的事情:

      pause() {
        if (this.state.status === false) {
           // Start your clock, whilst checking `cycle`
        } else {
           clearInterval(this.state.interval);
        }
      }
    

    这是一个 codepen,我在其中重构了您的代码,但基本上将所有逻辑移至 Pausehttps://codepen.io/stephenyu-the-encoder/pen/zYrqQYE

    我已将所有时钟更改为从 5 秒开始,这样可以更快地看到它工作。

    【讨论】:

    • 是的,这是我的第一次尝试,但是从不是 componentdidmount() 的方法运行间隔会使时间偏移变得奇怪(我认为它必须是由于异步更新)
    猜你喜欢
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    相关资源
    最近更新 更多