我的倒数时钟应该倒数一圈

问题描述 投票:0回答:2

我有一个正在工作的倒数时钟,除了它应该在倒数一圈开始倒数的事实之外。我有一个按钮,可以启动游戏并启动时钟。我按它,它检索并显示我的随机数(例如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
2个回答
0
投票

您没有发布generateRanNum的代码,但除非设置状态,否则第一次运行this.countdownClock()时,由于组件的初始化,state.ranNum仍然是null。您需要先设置该状态,然后才能开始递减计数。


0
投票

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

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

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

this.state在调用“下一轮”的componentWillUpdate()之前不会更新。但是,您在“本轮”中过早访问它。因此倒数落后一圈,因为它确实读取了旧值。

代码快速修复:

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

干杯。

© www.soinside.com 2019 - 2024. All rights reserved.