简体   繁体   English

将React计时器重置为初始常量值

[英]Reset React timer to initial const value

I'm trying to get my timer app to reset to the initial value in const initState when I hit the reset button, but it just stops the timer, without resetting the values. 我试图让我的计时器应用程序在我按下重置按钮时重置为const initState的初始值,但是它只是停止了计时器,而没有重置这些值。 I've tried a number of different solutions on Reset initial state in React + ES6 , but I've gotten the same results: the reset button just stops the timer, without actually resetting the values. 我已经在React + ES6中尝试了多种关于Reset初始状态的解决方案,但是得到了相同的结果:reset按钮只是停止计时器,而没有实际重置值。 Here's my code so far: 到目前为止,这是我的代码:

import React, { Component } from 'react';
import moment from 'moment';
import './App.scss';
import TimerHeader from './TimerHeader';
import TimerSettings from './TimerSettings';
import TimerDisplay from './TimerDisplay';
import TimerControls from './TimerControls';
import TimerFooter from './TimerFooter';

//set initial state w/default durations, clock set to 'SESSION', and not running

const initState = {
  currentTime: moment.duration(25, 'minutes'),
  sessionTime: moment.duration(25, 'minutes'),
  breakTime: moment.duration(5, 'minutes'),
  label: 'SESSION',
  running: false,
  timer: null 
}

class App extends Component {
  constructor(props) {
    super(props)

    this.state = initState;

    this.changeSessionTime = this.changeSessionTime.bind(this);
    this.changeBreakTime = this.changeBreakTime.bind(this);
    this.switchLabel = this.switchLabel.bind(this);
    this.switchTimer = this.switchTimer.bind(this);
    this.startTimer = this.startTimer.bind(this);
    this.stopTimer = this.stopTimer.bind(this);
    this.resetTimer = this.resetTimer.bind(this);
    this.countdown = this.countdown.bind(this);
    this.playAudio = this.playAudio.bind(this);
  }

  //new function to set currentTime to either sessionTime or breakTime based on label?

  //change the session and/or break times that are displayed
  changeSessionTime(newSessionTime) {
    this.setState({
      currentTime: !this.state.running && this.state.label === 'SESSION' ? newSessionTime.clone() : this.state.currentTime,
      sessionTime: newSessionTime
    })

  }

  changeBreakTime(newBreakTime) {
    this.setState({
      currentTime: !this.state.running && this.state.label === 'BREAK' ? newBreakTime.clone() : this.state.currentTime,
      breakTime: newBreakTime
    })
  }

  //change the clock setting when an active timer hits 0
  switchLabel() {
    this.setState({
      label: this.state.label === 'SESSION' ? '\xa0' + 'BREAK' : 'SESSION'
    })
  }

  //change the timer from session to break when an active timer hits 0
  switchTimer() {
    this.setState({
      currentTime: this.state.label === 'SESSION' ? this.state.sessionTime.clone() : this.state.breakTime.clone()
    })
  }


  //start the timer when start button is clicked
  startTimer() {
    if (this.state.running) {
      return
    } else {
      this.setState({
        running: true,
        timer: setInterval(this.countdown, 1000)
      })
    }
  }

  //stop the timer when stop (i.e., pause) button is clicked
  stopTimer() {
    if (!this.state.running) {
      return
    } else {
      this.setState({
        running: false,
        timer: clearInterval(this.state.timer)
      })
    }
  }

  //reset the timer when reset button is clicked
  resetTimer() {
    clearInterval(this.state.timer)
    this.setState(initState)
  }

  //reduce timer by the second when running === true
  countdown() {
    if (this.state.running) {
      this.setState({
        currentTime: this.state.currentTime.subtract(1, 'seconds')
      })
    }

    if (this.state.running && this.state.currentTime.get('minutes') <= 0 && this.state.currentTime.get('seconds') <= 0) {
      this.playAudio();
      this.switchLabel();
      this.switchTimer();
    }

  }

  playAudio() {
    const beep = document.getElementById("beep");
    beep.play();
  }


  render() {
    return (
      <div className="container-fluid container-clock">
        <TimerHeader />
        <TimerSettings currentTime={this.state.currentTime} sessionTime={this.state.sessionTime} breakTime={this.state.breakTime} label={this.state.label} running={this.props.running} changeSessionTime={this.changeSessionTime} changeBreakTime={this.changeBreakTime} />
        <TimerDisplay currentTime={this.state.currentTime} />
        <TimerControls startTimer={this.startTimer} stopTimer={this.stopTimer} resetTimer={this.resetTimer} />
        <TimerFooter />
      </div>
    );
  }
}


export default App;

Why isn't resetTimer() clearing the existing interval, and then putting the initial value to all of the values defined in the beginning 'const initState'? 为什么不resetTimer()清除现有间隔,然后将初始值放在开始的“ const initState”中定义的所有值上? Any insight would be helpful. 任何见解都会有所帮助。 Thanks! 谢谢!

the problem is that you are referencing the same object and then modifying the state, basically instead of doing: 问题是,您引用的是同一对象,然后修改状态,基本上不是这样做:

this.state = initState;

you need to do something like: 您需要执行以下操作:

this.state = Object.assign({}, initState);

and that will solve your problem. 那将解决您的问题。

 const initState = { number: 0, timer: null } class App extends React.Component { constructor() { super(); this.state = initState; this.start = this.start.bind(this); this.stop = this.stop.bind(this); } start() { const { timer } = this.state; if (timer) return null; this.setState({ timer: setInterval(() => { this.setState({ number: this.state.number + 1, }); }, 200), }); } stop() { const { timer } = this.state; clearInterval(timer); this.setState(initState); } render() { const { number } = this.state; return( <div> <div>{number}</div> <button onClick={this.start}>Start</button> <button onClick={this.stop}>Stop</button> </div> ); } } 

This should work, you can see example here: https://jsfiddle.net/iamgutz/t72zv9y8/18/ 这应该可行,您可以在此处查看示例: https : //jsfiddle.net/iamgutz/t72zv9y8/18/

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

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