【问题标题】:React seems to excute two functions at the same timeReact 似乎同时执行了两个函数
【发布时间】:2019-04-10 03:01:07
【问题描述】:

我做了一个简单的石头剪刀布游戏。在onclick 期间,我调用一个函数来添加一个数字并更改状态。在该函数中,我再调用 2 个函数,其中一个选择 1 到 3 之间的随机数并将其转换为石头/纸/剪刀并将其分配给状态,然后另一个函数找出谁赢了:

addToInput = val =>{
    this.setState({ 
        input:val
    });

    this.picknum();
    this.pickwin();       
}

https://codepen.io/russiandobby/pen/xeRYzw?editors=0002

一开始我以为picknumpickwin 会同时执行,但是即使我尝试在picknum 中调用pickwin,它仍然不起作用。

似乎发生的是,当pickwin 执行时,它会查看旧状态,而不是picknum 更改的状态。

我该如何解决这个问题?

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

setState 是异步的(或者至少可以是异步的),因此无法保证在您进入下一行代码时状态已更新如果您需要在设置状态后运行某些东西,要么放它在 componentDidUpdate 生命周期钩子中,或者将回调作为第二个参数传递给 setState。

例如,您可以跳过在 addToInput 函数中执行 pickWin,而是使用类似这样的 componentDidUpdate 函数:

componentDidUpdate(prevProps, prevState) {
  this.pickWin();
}

也就是说,与其设置状态,然后等待它更新,然后再次设置状态,我建议您重构代码,只调用一次 setState。如果你多次调用它,你有可能导致多次渲染,但看起来这些都是为了成为同一操作的一部分。也许更新您的 pickNum 和 pickWin 函数以返回一个值,而不是设置状态本身,然后调用 setState 一次并返回结果

picknum () {
  let aipick = ["rock","paper","scisors"];   
  let temp = Math.floor(Math.random() * 3) + 0  ;
  return aipick[temp]
}

pickWin(userChoice, aiChoice) {
  if (userChoice === 'rock' && aiChoice == 'scisors') {
    return 'USER WINS';
  }
  // etc
}

addToInput = val => {
  let aiChoice = pickNum();
  let winner = pickWin(val, aiNum);
  this.setState({
    aiChoice: aiChoice,
    whowon: winner,
    input: val,
  })
}

【讨论】:

  • 谢谢,我试过做回调,现在似乎可以了。
【解决方案2】:

好吧,看来回调可以是解决方案之一,所以我尝试做的是这个

  picknum (){

     let aipick=["rock","paper","scisors"];   
      let temp =Math.floor(Math.random() * 3) + 0  ;
  this.setState({
    aichoice:aipick[temp]
  },function(){
   this.pickwin();
 }
               )


}




  ////////////
addToInput = val =>{
   // console.log('add function');

 this.setState({ 

    input:val


  },function(){
   this.picknum();
 }

              );


 } 

现在似乎可以工作了。

【讨论】:

    【解决方案3】:

    是javascript的异步机制

     this.setState({ 
    
        input:val
    
    
      });
    

    如果你想同步。让我们使用异步/等待。 这是我的代码:

     addToInput = async val =>{
       // console.log('add function');
    
     await this.setState({ 
    
        input:val
    
    
      });
       await this.picknum();
      await this.pickwin();
    
     } 
    

    让我们试试吧!

    【讨论】:

    • 确实 setState 是(或可以是)异步的,但它不返回承诺,所以 await 无济于事。
    • 似乎已经解决了问题,除非我遗漏了什么
    • 等待一个非承诺只会将代码延迟到下一个微任务,并且不能保证它会等待你认为你正在等待的东西。如果添加 await 解决了问题,那么你很幸运。这不是解决此类问题的正确方法。
    • 那么如何解决此类问题。我想如果将所有内容都显示到一个函数中并且只使用一个 setstate 它会修复它,但还有其他方法可以修复它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 2016-12-20
    相关资源
    最近更新 更多