React:async setState更新到最晚

时间:2017-10-13 15:48:24

标签: javascript reactjs npm frontend

我正在学习React.js,并尝试开发一款简单的格斗游戏。

我尝试更新状态(下面的代码)来定义它的转向:

this.setState({ whoseRound: rand }, () => {
    console.log(this.state.whoseRound)
})

然后,我开始一个while循环。在我的循环中,我想知道使用我之前发起的状态whoseRound进行攻击的轮次。

我的问题是:由于函数setState是异步的,当我启动循环时,我的状态值仍为“0”。显然,我的runRound()方法结束时遇到了同样的问题。

如何正确解决该问题?

感谢所有人。

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      characters: [], //contains Array of characters objects
      readyToFight: false, // character selected or not
      firstPlayerCharacter: null, //contains key of character on select
      secndPlayerCharacter: null, //contains key of character on select
      whoseRound: 0 // defines whose character attacks
    }
  }

  //Run the fight
  setFight = () => {
    let firstFighter = this.state.characters[this.state.firstPlayerCharacter]
    let secndFighter = this.state.characters[this.state.secndPlayerCharacter]

    this.initiateFight(firstFighter, secndFighter);
  }

  //initiate fight rounds
  initiateFight = (firstFighter, secndFighter) => {

    // set who attacks first randomly => returns 1 or 2
    var rand = randomDice(1, 2)
    this.setState({whoseRound: rand}, () => {console.log('test:' + this.state.whoseRound)})

    while(firstFighter.stats.health > 0 || secndFighter.stats.healthh > 0){
      /* !!! depending on whoseRound is, we set an attacker 
    and a defenser !!! My probleme is that 
    this.state.whoseRound's value is 0 
    at this moment, as the sateState 
    method is async. */
      1 === this.state.whoseRound ? this.runRound(firstFighter, secndFighter) : this.runRound(secndFighter, firstFighter)
    }
  }

  // Lance les actions définies pour un round
  runRound = (attacker, defender) => {
    let hit = false
    let cc = false
    let damages

    hit = randomDice(0, 100) <= this.getHitChances(attacker, defender)
    cc = randomDice(0, 100) <= this.getCriticalChances(attacker, defender)
    damages = this.getDamages(attacker, defender, cc)

    if(hit)
    {
      //console.log(attacker.name + ' attaque ' + defender.name + ' et lui occtroie ' + damages + ' points de dégats')
      //console.log('les points de vie de ' + defender.name + ' passent de ' + defender.stats.health + ' à ' + (defender.stats.health - damages))
      defender.stats.health -= damages
    }

    //Now, it's the other character's turn
    1 === this.state.whoseRound ? this.setState({whoseRound: 2}) : this.setState({whoseRound: 1})

  }
  
}

export default App;

1 个答案:

答案 0 :(得分:0)

你可以做两件简单的事情,

首先:setState callback

中执行您想要的任何内容
this.setState({whoseRound: rand}, () => {
     console.log('test:' + this.state.whoseRound)
     while(firstFighter.stats.health > 0 || secndFighter.stats.healthh > 0){
      /* !!! depending on whoseRound is, we set an attacker 
    and a defenser !!! My probleme is that 
    this.state.whoseRound's value is 0 
    at this moment, as the sateState 
    method is async. */
      1 === this.state.whoseRound ? this.runRound(firstFighter, secndFighter) : this.runRound(secndFighter, firstFighter)
    }
})

第二:而不是使用state使用rand,因为您正在使用

更新状态
while(firstFighter.stats.health > 0 || secndFighter.stats.healthh > 0){
      /* !!! depending on whoseRound is, we set an attacker 
    and a defenser !!! My probleme is that 
    this.state.whoseRound's value is 0 
    at this moment, as the sateState 
    method is async. */
      1 === rand ? this.runRound(firstFighter, secndFighter) : this.runRound(secndFighter, firstFighter)
    }