【问题标题】:my countdown clock beings counting down one turn after it should我的倒计时时钟应该倒计时一圈
【发布时间】:2020-05-11 20:03:44
【问题描述】:

我有一个可以工作的倒计时时钟,只是它会在应该倒计时一圈后开始倒计时。我有一个按钮可以开始游戏并开始计时。我按下它,它会检索并显示我的随机数(比如 5)并显示我的随机输入数(5)。但倒计时显示 0。这是加载页面的 (20 * null)this.state 加载为 null)。我再次按开始,有一个新的随机数,但倒计时从 (5 * 20) 而不是新的随机数开始倒计时。我有点不知所措。任何帮助将不胜感激。

整个代码

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

let timer = null

class StartButton extends React.Component {
  render(props) {
      return (
        <button onClick={this.props.onClick}>{this.props.name}</button>
      )
    }
  }

class Header extends React.Component {
  constructor() {
    super();
      this.state = {
        ranNum: null,
        restart: false,
        timer: null
      };
  }

  handleClick() {
    clearTimeout(timer);
    this.clearForm();
    this.generateRanNum();
    this.generateInputs();
    // this.changeToRestartText()
    this.countdownClock();
  }

   generateRanNum = () => {
      let ranNum = Math.floor(Math.random() * 20);
       this.setState({
          ranNum: ranNum,
        })

    }

  clearForm = () => {
  if(this.state.restart === true){
      const inputLi = <Input />;
      inputLi.map(element => {
          element.remove()
      });
     const subButton = <SubmitButton />
      subButton.remove()
  }
}

countdownClock = async () => {
const startingNum = this.state.ranNum * 20;
for(let i = startingNum; i >= 0; i--) {
    await new Promise(resolve => {
        timer = setTimeout(() => {
         this.setState({
           timer: i
         })
        resolve()
     }, 1000)
   });
  }
}

generateInputs = () => {
    const inputs = []
    for(let i = 1; i <= this.state.ranNum; i++){
      inputs.push(
        <Input type='text' className='textInputs' />
      )
    }
    return inputs;
  }

  generateSubButton = () => {
    return (
      <SubmitButton name='Submit Button' />
    )
  }

  render() {
    return (
      <div>
        <header>
          <div className="headerContainer">
              <div id="countdown">
                <Countdown name='Countdown: ' countdown={this.state.timer} />
              </div>
              <div className="flex-item-header">
                <StartButton 
                    name={!this.state.restart ? 'Start Button' : 'Restart Button'}
                    onClick={() => this.handleClick()}
                />            
                </div>
              <div>
                  <DisplayCount name='Word Count: ' count={this.state.ranNum} />
              </div>
          </div>
        </header>
        <section>
          <div className="flex-main-item"> 
            <ul>
              {this.generateInputs()}
            </ul>
            {this.generateSubButton()}
          </div>
        </section>
      </div>
    )
  }
}

class SubmitButton extends React.Component {
  render(props) {
    return (
      <button name={this.props.name} onClick={this.props.onClick}>
      </button>
    )
  }
}

class DisplayCount extends React.Component {

  render() {
    return (
      <p>
        {this.props.name}
        <span>{this.props.count}</span>
      </p>
    )
  }
}

class Countdown extends React.Component {
  render(props) {
    return (
      <p>
        {this.props.name}
        <span>{this.props.countdown}</span>
      </p>
    )
  }
}

【问题讨论】:

    标签: javascript reactjs this countdown countdowntimer


    【解决方案1】:

    您没有发布generateRanNum 的代码,但除非它设置状态,否则您第一次运行this.countdownClock()state.ranNum 从组件的初始化仍然是null。在开始倒计时之前,您需要先设置该状态。

    【讨论】:

    • 刚刚发布了generateRanNum函数。我还是个新手,但我认为我正确设置了 ranNum,除非我不能使用带有 this.state 对象的变量
    • 访问整个代码将有助于查看方法所在的位置等,但我怀疑从您的 generateRanNum 函数中删除 return 语句将解决问题。您无需返回任何内容,只需更新状态即可。我怀疑this 指的不是你想要的东西。
    【解决方案2】:

    故事寓意:在 React 中设置组件状态是异步的。

    您将ranNum 状态设置为generateRanNum(),然后在countdownClock() 中读取this.state.ranNum,期望它是最新的。嗯,这不是因为setState() 是异步的。

    我猜你知道组件生命周期的概念。任何对setState() 的调用都会导致对生命周期钩子方法的一轮调用。但出于性能原因,这些调用被缓冲并批量应用,因此是异步的。

    this.state 在调用“下一轮”的componentWillUpdate() 之前不会更新。然而,您在“这一轮”中过早地访问它。因此倒计时滞后一圈,因为它确实读取了旧值。

    快速修复您的代码:

    const ranNum = this.generateRanNun();
    this.countdownClock(ranNum);
    

    干杯。

    【讨论】:

    • 这完全解决了问题。非常感谢。出于好奇,我的一些函数在使用 this.state.ranNum 时工作得很好,为什么该变量可用于某些事情,而其他人基本上不能在同一个“回合”中使用?
    • 如果你的意思是generateInputs(),它可以工作,因为它是在render()方法内部调用的,这不是同一轮。
    • “圆”是模糊的,想想事件循环模型,就清楚多了。如果你不熟悉这个概念,我强烈建议你阅读一下。
    • 我一定会读到的!目前我对它的了解非常模糊。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-20
    • 1970-01-01
    相关资源
    最近更新 更多