-1

So i'm trying to make a "Rock Paper Scissors" game, and everything seems to work out, but when i click a button, for example "Rock", i have to click it three times in order for it to work.

This is my code:

class RPSGame extends Component {
constructor(props) {
    super(props);
    this.state = {
        p1Option: 'rock',
        p2Option: 'rock',
        winner: 'Tie',
        winnerMsg: 'Its a Tie!'
    };
    this.handleClick = this.handleClick.bind(this);
    this.calculateWinner = this.calculateWinner.bind(this);
}
handleClick(e) {
    this.setState({ p1Option: e.option });
    this.calculateWinner();
}
calculateWinner() {
    let { p1Option, p2Option } = this.state;

    if (p1Option === p2Option) {
        this.setState({ winner: 'Tie' });
    } else if (
        (p1Option === 'rock' && p2Option === 'paper') ||
        (p1Option === 'paper' && p2Option === 'scissors') ||
        (p1Option === 'scissors' && p2Option === 'rock')
    ) {
        this.setState({ winner: 'Player Two' });
    } else if (
        (p1Option === 'rock' && p2Option === 'scissors') ||
        (p1Option === 'paper' && p2Option === 'rock') ||
        (p1Option === 'scissors' && p2Option === 'paper')
    ) {
        this.setState({ winner: 'Player One' });
    } else {
        console.log('error!');
    }
}

And inside my render:

    render() {
    const { handleClick } = this;
    const {  p1Option, p2Option } = this.state;
    return (
        <div>
            <h1>Rock Paper Scissors</h1>
            <p>Player 1 chose: "{p1Option}"</p>
            <p>Player 2 chose: "{p2Option}"</p>
            <button
                onClick={() =>
                    handleClick({
                        option: 'rock'
                    })}
            >
                Rock
            </button>
            <button
                onClick={() =>
                    handleClick({
                        option: 'paper'
                    })}
            >
                Paper
            </button>
            <button
                onClick={() =>
                    handleClick({
                        option: 'scissors'
                    })}
            >
                Scissors
            </button>
        </div>
    );
}

Sorry if my code is bulky, but im just starting with React and i plan to shorten it once i solve this problem.

Thanks in advance.

Marteam
  • 29
  • 4

1 Answers1

1

React state is async, that means when you call calculateWinner you still don't have the last pushed state in the function scope.

enapupe
  • 15,691
  • 3
  • 29
  • 45
  • you can simply pass in a function as a second argument to setState. This function runs after your state has been mutated. [try this](https://stackoverflow.com/questions/42018342/is-there-a-synchronous-alternative-of-setstate-in-reactjs) – Ashish Tuteja Jan 15 '21 at 18:50
  • Thanks! to both of you!, instead of passing calculateWinner after setting state, i passed it as a second argument. – Marteam Jan 15 '21 at 19:18