[SOLVED]this.setState is updating state after console.log

[SOLVED]this.setState is updating state after console.log
0

#1

Hello again everyone, I am building a rock-paper-scissors app in react and have run into a problem. I am testing the app by console.logging the id of the target pic pressed(rock paper or scissors) but the thing is I am console logging the same thing multiple times after a different option being pressed. If I press “scissors”, and then press “paper”,it will log “scissors” twice. I read that setState is asynchronous but I still don’t know how to fix the issue. I am sure it is a rather simple fix to get the state to properly display the selected attribute, as console.logging event.target.id is working perfectly fine. Thanks everyone,
Here is a link to my codepen

Here is the JSX if you just want to read that

var options = ["rock", "paper", "scissors"]

class Game extends React.Component {
    constructor(props){
      super(props);
     this.state={
       score: 0,
       playerMove:"",
       compMove:"",
     }; 
      this.evaluate=this.evaluate.bind(this);
      this.calculateScore = this.calculateScore.bind(this);
    }

    calculateScore(){

    }

    evaluate(event){
      var compMove = Math.floor(Math.random() * 3);
      this.setState({
        compMove: options[compMove],
        playerMove: event.target.id
      });
      console.log(this.state.playerMove)
    }
    render(){
      return(
        <div className="text-center box">
              <h1 className="display-3">Rock-Paper-Scissors</h1>
              <img src="https://www.randomlists.com/img/rock-paper-scissors/rock.png" className="img-thumbnail" onClick={this.evaluate} id="rock" />
              <img src="https://icons.veryicon.com/png/System/Icons8%20Metro%20Style/Rock%20Paper%20Scissors%20Paper.png" className="img-thumbnail" id="paper"  onClick={ this.evaluate}/>
            <img src="https://icons.veryicon.com/png/System/Icons8%20Metro%20Style/Rock%20Paper%20Scissors%20Scissors.png" className="img-thumbnail" id="scissors" onClick={ this.evaluate}/>
        </div>
      )
    }
}


ReactDOM.render(<Game />, document.getElementById("app")
)

Thanks again!


#2

Yes, setState is async. One easy way to handle that is to give it a callback, so instead of:

this.setState({
        compMove: options[compMove],
        playerMove: event.target.id
      });
      console.log(this.state.playerMove)

do:

this.setState({
        compMove: options[compMove],
        playerMove: event.target.id
      }, console.log(this.state.playerMove));

Of course, it shouldn’t matter as far as the DOM is concerned, but when debugging, yes, that can be a pain. Fortunately it accepts a callback to run after it is done.


#3

Thanks KevinSmith! I didn’t know if it would negatively effect the program later on. I had to add a ()=> before the console.log but it the tests are working perfectly fine now :slight_smile: