我有一个正在工作的倒数时钟,除了它应该在倒数一圈开始倒数的事实之外。我有一个按钮,可以启动游戏并启动时钟。我按它,它检索并显示我的随机数(例如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>
)
}
}
您没有发布generateRanNum
的代码,但除非设置状态,否则第一次运行this.countdownClock()
时,由于组件的初始化,state.ranNum
仍然是null
。您需要先设置该状态,然后才能开始递减计数。
故事的寓意:在React中设置组件状态是异步的。
您在ranNum
中设置了generateRanNum()
状态,然后在this.state.ranNum
中读取了countdownClock()
,希望它是最新的。嗯,这不是因为setState()
是异步的。
我想您知道组件生命周期的概念。对setState()
的任何调用都将导致对生命周期挂钩方法的一轮调用。但是出于性能原因,这些调用被缓冲并批量应用,因此是异步的。
this.state
在调用“下一轮”的componentWillUpdate()
之前不会更新。但是,您在“本轮”中过早访问它。因此倒数落后一圈,因为它确实读取了旧值。
代码快速修复:
const ranNum = this.generateRanNun();
this.countdownClock(ranNum);
干杯。