在我正在制作的这个游戏中,用户输了之后我清除了setInterval。当他们单击再次播放时?我希望计时器重新启动,但是在使用React时,我很难做到这一点。我已经尝试了多种方法,例如将计时器分离为自己的组件,创建帮助器功能以及使用生命周期方法,但是我似乎无法理解这一部分。我可以正常启动并清除setInterval,但是重新启动它是我的问题。
import React, {Component} from 'react';
// helper function to set a random action
function setRandomAction() {
let actions = ['bop it', 'pull it', 'twist it'];
let rando = actions[Math.floor(Math.random() * actions.length)];
return rando;
}
class BopIt extends Component {
constructor(props) {
super(props);
// set initial action in this.state so it is not empty on pageload
this.state = {
action: setRandomAction(),
countdown: 3,
userPressed: '',
play: true
}
this.bind = this.keyPressed.bind(this);
this.bind = this.keepPlaying.bind(this);
this.bind = this.timer.bind(this);
this.bind = this.startTimer.bind(this);
this.bind = this.endGame.bind(this);
this.quitGame = this.quitGame.bind(this);
this.playAgain = this.playAgain.bind(this);
}
componentDidMount() {
this.keyPressed();
this.startTimer();
}
startTimer() {
let setTimerTime = parseInt(`${this.state.countdown - 2}000`);
this.stopIntervalId = setInterval(() => this.timer(), setTimerTime);
}
componentWillUnmount() {
this.startTimer();
this.keyPressed();
this.keepPlaying();
this.endGame();
}
timer() {
var count = this.state.countdown;
if (count === 0) {
count = 4
}
this.setState({countdown: count - 1});
}
keyPressed() {
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowLeft') {
this.setState({
userPressed: 'pull it'
});
} else if (e.key === 'ArrowDown') {
this.setState({
userPressed: 'bop it'
});
} else if (e.key === 'ArrowRight') {
this.setState({
userPressed: 'twist it'
});
} else {
// this.endGame();
this.setState({
userPressed: 'wrong'
});
}
if (this.state.userPressed !== this.state.action) {
this.endGame();
} else {
this.keepPlaying();
}
});
}
keepPlaying() {
let actions = ['bop it', 'pull it', 'twist it'];
let rando = actions[Math.floor(Math.random() * actions.length)];
this.setState({
action: rando,
userPressed: ''
});
}
endGame() {
console.log('You Lost!!!');
this.setState({
play: false
});
}
quitGame() {
clearInterval(this.stopIntervalId);
}
playAgain() {
this.setState({
play: true,
action: setRandomAction(),
countdown: 3
});
}
render() {
// if (this.state.countdown <= 0) {
// this.endGame();
// }
console.log(this.state)
let gameAction = `${this.state.action} ${this.state.countdown}`;
return (
<div className="bop-it">
<div className="show-action">
{this.state.play ? gameAction : <ResetGame playAgain={this.playAgain} quitGame={this.quitGame}/> }
</div>
<span>Pull It</span>
<br/>
<span>Bop It</span>
<br/>
<span>Twist It</span>
</div>
);
}
}
class ResetGame extends Component {
render() {
return (
<div>
<input type="button" value="Play Again?" onClick={this.props.playAgain}/>
<input type="button" value="Quit Game?" onClick={this.props.quitGame}/>
</div>
);
}
}
export default BopIt
编辑:
我最终在this.startTimer()
方法的末尾简单地调用了playAgain()
。我本可以发誓以前做过,但显然没有。我还要确保只在一个地方调用clearInterval
,以便在应用程序的其他部分不会出现冲突。
我遇到的另一个问题是,每当我重启setInterval
时,计时器就会以更快的速度倒计时。因为这个原因:
let setTimerTime = parseInt(`${this.state.countdown - 2}000`);
this.stopIntervalId = setInterval(() => this.timer(), setTimerTime);
我把那行代码放在这里,因为我最终希望用户选择游戏速度,但这完全搞砸了我应用状态对象的countdown
属性。现在删除该行也消除了一些混乱。
import React, {Component} from 'react';
// helper function to set a random action
function setRandomAction() {
let actions = ['bop it', 'pull it', 'twist it'];
let rando = actions[Math.floor(Math.random() * actions.length)];
return rando;
}
class BopIt extends Component {
constructor(props) {
super(props);
// set initial action in this.state so it is not empty on pageload
this.state = {
action: setRandomAction(),
countdown: 3,
userPressed: '',
play: true
}
this.bind = this.keyPressed.bind(this);
this.bind = this.keepPlaying.bind(this);
this.bind = this.endGame.bind(this);
this.bind = this.timer.bind(this);
this.bind = this.startTimer.bind(this);
this.quitGame = this.quitGame.bind(this);
this.playAgain = this.playAgain.bind(this);
}
componentDidMount() {
this.keyPressed();
this.startTimer();
}
startTimer() {
// let setTimerTime = parseInt(`${this.state.countdown - 2}000`);
this.stopIntervalId = setInterval(() => this.timer(), 1000);
}
componentWillUnmount() {
this.keyPressed();
this.keepPlaying();
this.endGame();
}
timer() {
let count = this.state.countdown;
if (count === 0) {
count = 4
// end the game if the timer hits 0
this.endGame();
}
this.setState({countdown: count - 1});
}
keyPressed() {
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowLeft') {
this.setState({
userPressed: 'pull it'
});
} else if (e.key === 'ArrowDown') {
this.setState({
userPressed: 'bop it'
});
} else if (e.key === 'ArrowRight') {
this.setState({
userPressed: 'twist it'
});
} else {
this.setState({
userPressed: 'wrong'
});
}
// if user presses wrong key, then the game is over
if (this.state.userPressed !== this.state.action) {
this.endGame();
} else {
// otherwise, reset the time and chooose a random action
this.keepPlaying();
}
});
}
keepPlaying() {
this.setState({
action: setRandomAction(),
countdown: 3,
userPressed: ''
});
}
endGame() {
console.log('You Lost!!!');
this.setState({
play: false
});
clearInterval(this.stopIntervalId);
}
quitGame() {
// clearInterval(this.stopIntervalId);
console.log('you have left the game')
}
playAgain() {
this.setState({
play: true,
action: setRandomAction(),
countdown: 3
});
this.startTimer();
}
render() {
let gameAction = `${this.state.action} ${this.state.countdown}`;
return (
<div className="bop-it">
<div className="show-action">
{this.state.play ? gameAction :
<ResetGame
playAgain={this.playAgain}
quitGame={this.quitGame}
/>
}
</div>
<span>Pull It</span>
<br/>
<span>Bop It</span>
<br/>
<span>Twist It</span>
</div>
);
}
}
class ResetGame extends Component {
render() {
return (
<div>
<input type="button" value="Play Again?" onClick={this.props.playAgain}/>
<input type="button" value="Quit Game?" onClick={this.props.quitGame}/>
</div>
);
}
}
export default BopIt
答案 0 :(得分:1)
我认为问题可能在于,您同时设置了2个定时器,分别在componentWillUnmount
中设置了一个,在componentWillMount
中设置了另一个,并且在删除它们时只删除了其中一个,因为其他人因变量覆盖而迷路
我会在您的代码上更改以下方法,以便创建重复的计时器会更加困难,并且在再次播放后还会触发计时器
startTimer() {
let setTimerTime = parseInt(`${this.state.countdown - 2}000`);
if (!this.stopIntervalId) {
this.stopIntervalId = setInterval(() => this.timer(), setTimerTime);
}
}
quitGame() {
clearInterval(this.stopIntervalId);
this.stopIntervalId = undefined;
}
playAgain() {
this.setState({
play: true,
action: setRandomAction(),
countdown: 3
});
this.startTimer()
}