setState using Conditionals

Im doing the React Library course currently thought I would change the challenge a little bit it is essentially a 50/50 program that prints you win or you lose and tracks how many turns it takes. I wanted to add counters to track Wins and Losses as well but don’t understand how to implement it thus far this is what I tried first. My question is essentially how do you use Conditionals to setState I attempted this in the handleClick function with no luck.

class Results extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <h1>{
      this.props.fiftyFifty
        ?'You Win!'
        :'You Lose!'
    }</h1>;
  }
}

class GameOfChance extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0,
      wins: 0,
      losses: 0
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(expression) {
    this.setState(state => ({
        counter: state.counter + 1
    }));
    if (expression == true){
      this.setState(state => ({
        wins: state.wins + 1
      }))
    } else {
      this.setState(state => ({
        losses: state.losses + 1
      }))
    }
  }



  render() {
    const expression = Math.random() >= .5; 
    return (
      <div>
        <button onClick={this.handleClick}>Play Again</button>
        {/* Change code below this line */}
  <Results fiftyFifty={expression} />
        <p>{'Turn: ' + this.state.counter}</p>
        <p>{'Wins: ' + this.state.wins}</p>
        <p>{'Losses: ' + this.state.losses}</p>
      </div>
    );
  }
}

Cool.

I think in this case you’re going to want to store that value in state so it doesn’t change on rerenders and so you can manipulate what you want.

I also think here:

    this.state = {
      counter: 0,
      wins: 0,
      losses: 0
    };

One of those is redundant. I would get rid of counter - it is just the other two added together.

I would just have my handleClick handle everything.

Another advantage of handling it is way is that you can have it not run the game until the button is pressed - it doesn’t autorun when it loads. (If you want it to autorun, you can put it in the lifecycle method, compenentDidMount.)

This is what I came up with. There are ways to significantly simplify this, but I wanted to keep it at your level of learning.

class GameOfChance extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isWin: 0,
      wins: 0,
      losses: 0,
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    const isWin = Math.random() >= 0.5;
    this.setState((state) => ({
      isWin,
      wins: isWin ? state.wins + 1 : state.wins,
      losses: isWin ? state.losses : state.losses + 1,
    }));
  }

  render() {
    const turns = this.state.wins + this.state.losses;
    return (
      <div>
        <button onClick={this.handleClick}>Play Again</button>
        {turns ? (
          <Results fiftyFifty={this.state.isWin} />
        ) : (
          <h1>No results yet.</h1>
        )}
        <p>{"Turn: " + turns}</p>
        <p>{"Wins: " + this.state.wins}</p>
        <p>{"Losses: " + this.state.losses}</p>
      </div>
    );
  }
}

Thanks so much that works amazing I understood my big issue was not being able to access the Math.random expression from the function so putting it straight in was a great solution, surprised I didn’t think of that. Didn’t even know you could use Ternary expressions not just for rendering. I learned heaps from this thanks so much

1 Like

Yeah, it’s pretty common to use ternary operators and also the short-circuit && for rendering. But be careful - some people like to use it for large blocks of code and that can be confusing. But here it’s short and clear.

And when in doubt, check the excellent React docs: