反应和设置间隔(FCC Pomodoro计时器..)

时间:2020-03-11 06:07:35

标签: javascript reactjs

在React中使用setInterval时遇到一些问题。

基本上,我正在尝试为FreeCodeCamp构建一个Pomodoro计时器,而setInterval无法识别该函数已定义。.下面的链接。

https://codepen.io/paalpwmd/pen/yLNJEMv?editors=1111

基本上-我希望计时器方法从总长度状态中减去1000ms,直到长度为0。

我得到的错误是这个。

TypeError: this.tick is not a function 
 at https://cdpn.io/boomboom/v2/index.html?editors=1111&key=iFrameKey-713a6d83-4480-ba30-a898-c7e72b527740:28

我也尝试过将set interval函数直接放在计时器内部(像这样),但我收到一条错误消息,说this.state是未定义的。

timer(){
    setInterval(function() {
      this.setState({
      length: this.state.length - 1000 
}), 1000)
}

我已经尝试了ES6和ES5语法,这在构造函数中是必不可少的。

我认为这与React绑定它的方式有关。我在这里做什么错了?

1 个答案:

答案 0 :(得分:1)

setInterval回调function更改为arrow function

setInterval将调用回调函数时,this将引用setInterval object

如果状态更新取决于先前的状态,请始终在setState中使用callback

尝试一下。

  timer() {
    setInterval(() => {
      this.tick();
      console.log("tick");
    }, 1000)
  }

工作示例:

class PomTimer extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      break: 300000,
      length: 1500000,
      clockFace: ''
    }
    this.clockify = this.clockify.bind(this);
    this.timer = this.timer.bind(this);
    this.reset = this.reset.bind(this);
    this.tick = this.tick.bind(this);
  }

  reset() {
    this.setState({
      break: 300000,
      length: 1500000
    })
    this.clockify();
  }

  tick() {
    //console.log("tick: " + this.state.length);
    if (this.state.length > 0) {
      this.setState( (preState) => {
        return {
            length: preState.length - 1000
        }
      })

    } else {

    }
  }

  clockify() {
    let minutes = Math.floor(this.state.length / 60000);
    let seconds = (this.state.length % 60000) / 1000
    this.setState({
      clockFace: `${minutes}:${seconds}`
    })
  }


  timer() {
    setInterval(() => {
      this.tick();
    }, 1000)
  }

  componentDidMount() {
    this.clockify();
  }
  render() {
    return <div>
      <h1>Pomodoro Clock</h1>
      <div id="break-label">
        <div id="break-increment" onClick={this.breakInc}>+</div>
        <p id="break-length">Break Length: {this.state.break / 60000}</p>
        <div id="break-decrement" onClick={this.breakDec}>-</div>
      </div>

      <div id="session-label">
        <div id="session-increment" onClick={this.sessionInc}> + </div>
        <p id="session-length">Session Length {Math.ceil(this.state.length / 60000)} ({this.state.length})</p>
        <div id="session-decrement" onClick={this.sessionDec}> - </div>

      </div>
      <div id="session">

        <p id="time-left"> Session: {this.state.clockFace} </p>
      </div>
      <button onClick={this.clockify}>test</button>
      <button onClick={this.resetTimer}>Reset</button>
      <button onClick={this.timer}>Timer</button>
    </div>
  }
}
ReactDOM.render(<PomTimer />, document.getElementById("react-root"));
#react-root {
  width: 50%;
  display: flex;
  margin: auto;
  border: 2px solid black;
  border-radius: 50px;
  justify-content: center;
  
}
body {
  background-color: #1E555C;
  font-family: 'Verdana'
}

#break-increment, #break-decrement, #session-increment, #session-decrement{
  cursor: pointer;
  margin: 0px 5px;
  border: 1px solid black;
  border-radius: 5px;
  width: 20px;
  height: 20px;
  text-align: center;
  background-color: #1E777C;
}

#session-label, #break-label, #session {
   display: flex;
  flex-direction: row;
  justify-content: center;
  padding-top: 50px;
}
#break-length, #session-length{
margin: 0;
}

#time-left {
  font-size: 2rem;
}
<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>
<div id="react-root">