【问题标题】:Reset React timer to initial const value将 React 计时器重置为初始 const 值
【发布时间】:2019-05-09 10:25:44
【问题描述】:

当我点击重置按钮时,我试图让我的计时器应用程序重置为const initState 中的初始值,但它只是停止计时器,而不重置值。我在Reset initial state in React + ES6 上尝试了许多不同的解决方案,但我得到了相同的结果:重置按钮只是停止计时器,而没有实际重置值。到目前为止,这是我的代码:

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;

为什么resetTimer() 不清除现有区间,然后将初始值放入开头“const initState”中定义的所有值?任何见解都会有所帮助。谢谢!

【问题讨论】:

  • 也许你可以在下面看到我的例子+1

标签: javascript reactjs timer scope constants


【解决方案1】:

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

这应该可行,您可以在此处查看示例:https://jsfiddle.net/iamgutz/t72zv9y8/18/

【讨论】:

  • @stephan 如果你没看到,也许你可以试试我的例子。
  • 我看到了,谢谢。我仍然不完全确定您的解决方案为什么有效...您将initState 创建为const,并将该值设置为构造函数中的状态...但是为什么stop() 方法允许您重置计时器?
【解决方案2】:

问题是你引用同一个对象然后修改状态,基本上不是这样做:

this.state = initState;

您需要执行以下操作:

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

这将解决您的问题。

【讨论】:

  • 谢谢!我明白为什么这应该起作用,但不幸的是它仍然在做同样的事情。这是我认为正在发生的事情:Object.assign() 克隆initState 并将这些值分配给this.state。理论上,这应该意味着任何时候状态发生变化,initState 仍然保持不变。然而 resetTimer() 函数仍然无法以这种方式工作......不确定我在这里缺少什么。
猜你喜欢
  • 2021-08-08
  • 1970-01-01
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-14
  • 2021-09-09
相关资源
最近更新 更多