在React中的clearInterval之后重新启动setInterval

时间:2018-09-08 16:44:22

标签: javascript reactjs setinterval clearinterval

在我正在制作的这个游戏中,用户输了之后我清除了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

1 个答案:

答案 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()
}