简体   繁体   English

箭头 function 存储在 State

[英]Arrow function stored in State

So i have this problem, which i don't know if it's a concept wrongly had or a bad implementation of that concept.所以我有这个问题,我不知道这是一个错误的概念还是该概念的错误实施。 Im doing the pomodoro clock in freecodecamp.org which forces me to use setInterval() function from plain js and in a React component.我在 freecodecamp.org 中做番茄钟,这迫使我在纯 js 和 React 组件中使用 setInterval() function。

Inside the Pomodoro component, every time it gets mounted in the DOM tree should run a setInterval checking for the state and clocking depending on the state of the component.在 Pomodoro 组件内部,每次将其挂载到 DOM 树中时,都应运行 setInterval 检查 state 并根据组件的 state 进行计时。 In fact, i can see the state variables change (thanks to the React Debugging tool) but the interval not working事实上,我可以看到 state 变量发生变化(感谢 React 调试工具)但间隔不起作用

componentdidmount runs after having the component rendered inside the DOM tree and checks the state.status, if its true checks what cycle to run, whether if its the session or break clock.After one timer ends, the other should start immediately. componentdidmount 在将组件渲染到 DOM 树中后运行并检查 state.status,如果其为 true,则检查运行哪个周期,无论是 session 还是中断时钟。一个计时器结束后,另一个应该立即启动。

This timer or interval is stored in the component state and then cleared from the this.state.interval state.此定时器或间隔存储在组件 state 中,然后从 this.state.interval state 中清除。


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


}  





the clock isn't working due saving the setInterval into the Component state or its due something else?由于将 setInterval 保存到组件 state 或其他原因,时钟无法正常工作?

EDIT编辑

Added a codepen so you can see the live version and states changing添加了一个 codepen,以便您可以看到实时版本和状态变化

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

EDIT II编辑二

Erased the componentdidmount method and moved the content to pause() method but now both clocks run at the same time and clocks run faster than intended (might be problem coming from the async state updates in react?)删除了 componentdidmount 方法并将内容移至 pause() 方法,但现在两个时钟同时运行并且时钟运行速度比预期快(可能是来自异步 state 更新的问题?)

The issue is your usage of componentDidMount .问题是您对componentDidMount的使用。 It is invoked when the Component is mounted, which means it is invoked before the user can interact with the screen.它在组件被挂载时被调用,这意味着它在用户可以与屏幕交互之前被调用。

Your check你的支票

if (this.state.status) 

Will never be true, as your state sets status to false.永远不会是真的,因为您的 state 将status设置为假。 Looking at your code, I assume you meant that the Pause Button to toggle status to be true, and you felt that the code within componentDidMount would run.查看您的代码,我假设您的意思是暂停按钮将状态切换为 true,并且您认为componentDidMount中的代码会运行。


What you should do however, is move your code into the pause() function, as this is actually the trigger for your clock.但是,您应该将代码移动到pause() function 中,因为这实际上是时钟的触发器。

From there you can do something similar to:从那里你可以做类似的事情:

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

Here is a codepen, where I have refactored your code, but basically moved all the logic into Pause .这是一个 codepen,我在其中重构了您的代码,但基本上将所有逻辑都移到了Pause中。 https://codepen.io/stephenyu-the-encoder/pen/zYrqQYE https://codepen.io/stephenyu-the-encoder/pen/zYrqQYE

I've changed all the clocks to start at 5 seconds so it's faster to see it working.我已将所有时钟更改为从 5 秒开始,这样可以更快地看到它工作。

I suspect the problem with your clocks running at the same time and the timer being off is a result of not stopping the old timer before kicking off the new one.我怀疑您的时钟同时运行并且计时器关闭的问题是由于在启动新计时器之前没有停止旧计时器。

What you might be looking for is the componentDidUpdate method.您可能正在寻找的是componentDidUpdate方法。 This method lets you compare your last state to your current state, and make changes accordingly.此方法可让您将最后的 state 与当前的 state 进行比较,并进行相应的更改。 Using that method, you can check when we switch from break time to session time, and then stop the old timer to kick off the new one like so:使用该方法,您可以检查我们何时从中断时间切换到 session 时间,然后停止旧计时器以启动新计时器,如下所示:

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

This way, as long as when your session or break timer reaches 0 you toggle this.state.cycle , you'll always be kicking off the new timer.这样,只要当您的 session 或中断计时器达到 0 时,您切换this.state.cycle ,您将始终启动新计时器。

Check out my new codepen here for fully functional code在此处查看我的新代码笔以获取功能齐全的代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM