Issues with React - Render Conditionally from Props

I am attempting to complete the ‘Render Conditionally from Props’ problem and am getting two test cases that continually fail. I’ve run the code and everything is working as stated by the problem. Any ideas?

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

class GameOfChance extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 1
    }
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState({
      counter: this.state.counter + 1
    });
  }
  render() {
    let expression = Math.random() > .5;
    return (
      <div>
        <button onClick={this.handleClick}>Play Again</button>
        { /* change code below this line */ }
        <Results fiftyFifty={expression}/>
        { /* change code above this line */ }
        <p>{'Turn: ' + this.state.counter}</p>
      </div>
    );
  }
};

Good - The GameOfChance component should exist and render to the page.

Good - GameOfChance should return a single button element.

Good - GameOfChance should return a single instance of the Results component, which has a prop called fiftyFifty.

Failing(But working in test window) - GameOfChance state should be initialized with a property of counter set to a value of 1.
When the GameOfChance component is first rendered to the DOM, a p element should be returned with the inner text of Turn: 1.

Good - When the GameOfChance component is first mounted to the DOM and each time the button is clicked thereafter, a single h1 element should be returned that randomly renders either You Win! or You Lose!.

Failing(But working in test window) - Each time the button is clicked, the counter state should be incremented by a value of 1, and a single p element should be rendered to the DOM that contains the text “Turn: N”, where N is the value of the counter state.

3 Likes
      <h1>
      {
        this.props.fiftyFifty ? <p>You win!</p> : <p>You lose!</p>
      }
      </h1>

So, you are in JSX. JSX looks like HTML, but once you are inside curly braces, you are doing JavaScript. So, in your conditional statement, you don’t give it <p>You win!</p> (HTML), you want to give it JavaScipt, i.e., a string. The JSX will then pass it out to the HTML. To put it shortly, those should not be <p> tags but just a simple string.

1 Like

Kevin’s right. Plus, it’s kind of weird to render a <p> inside an <h1>. Also, Results looks like it can be turned into a functional component since it doesn’t handle any local state (it just get’s props from GameOfChance). Like this:

function Results(props) {
  return (
    <h1>
      { props.fiftyFifty ? 'You win!' : 'You lose!' }
    </h1>
  )
}

The rest looks good. Not sure why the test for the state of counter is not passing. Perhaps add a , Not really needed, but, the test suite might be expecting it:

  class GameOfChance extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        counter: 1,
      }
      this.handleClick = this.handleClick.bind(this);
    }
2 Likes

True, that could be a functional component, but that was given by the tutorial so there is no need to change it.

1 Like

Ah, did not know that. Thanks for the clarification Kevin!

I’m having a similar issue. The error i’m getting is: “When the GameOfChance component is first mounted to the DOM and each time the button is clicked thereafter, a single h1 element should be returned that randomly renders either You Win! or You Lose!.”

Does anyone know why and can explain it to me? Here is my code:

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: 1
    }
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState({
      counter: this.state.counter + 1
    });
  }
  render() {
    let expression = Math.random()> 0.5;
    return (
      <div>
        <button onClick={this.handleClick}>Play Again</button>
        { /* change code below this line */ }
<Results fiftyFifty = {this.expression}/>

        { /* change code above this line */ }
        <p>{'Turn: ' + this.state.counter}</p>
      </div>
    );
  }
};

Thanks!

I’ve edited your post for readability. When you enter a code block into the forum, precede it with a line of three backticks and follow it with a line of three backticks to make easier to read. See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.

markdown_Forums

Your problem is here:

<Results fiftyFifty = {this.expression}/>

expression is a local variable to this method, there is no need to reference it with this - that would only be if it were a member of the class, afaik. If you get rid of this, it should work.

1 Like

I actually had an issue where the parser wasn’t loading and it wouldn’t let me advance. For some reason copying and pasting the code in works.

any idea why
let expression = function() {return Math.random() > .5;}
didn’t work and
let expression = Math.random() > .5;
did?
with the former i kept getting either only true or only false if i kept clicking play again

Because those are two different things. In the first case you are sending a function and in the second case you are sending a boolean. The component (as written) is expecting a boolean value.

This is easy to see. Go to the render method of your Results component and add the line:

    console.log('Results props', this.props.fiftyFifty, !!this.props.fiftyFifty)

as the first line of the render method. If you open up your browser console you can see what Results is getting. First it shows you what fiftyFifty is and then if it is “truthy” (the !! is a trick to turn any value to a boolean.) If you test the first method, you will see that the function always evaluates as “true” because a function is “truthy”. The key here is that the function never gets run. It just evaluates to true and the game always wins - it never looses.

Now, the app could have been designed differently. What if you want to send a function instead of the result of the function? Then you can call the function inside the Results component. If you change the jsx in Results to:

this.props.fiftyFifty() ? 'You win!' : 'You lose!'

Now you’ve received a function and you are invoking that function. This will pass the test. The difference is that the app is designed to evaluate to a boolean when expression is defined. Here we’ve changed it so we’re just creating a function, passing that to Results and evaluating the function there.

But as the problem is written, the component expects a boolean value so that is what we should send it, not a function that will give us a boolean if we run it.

So let me ask you guys this… I have also done the challenge the same way, but I looked at their hint as well to see how they do it… Somehow they are putting this all in the render section and it looks like it is referring to results… but honestly I just don’t get how they are doing it…

render() {
    let expression = Math.random() > .5;
    {(expression == 1) ? <Results fiftyFifty = "You win!"/> : <Results fiftyFifty = "You lose!" />}

to me this is super confusing, can anyone take a stab at explaining how this works?

Yeah, that is confusing.

(expression == 1)

This makes no sense to me. expression is a boolean. They are doing a non-strict equals with a number. OK, so 1 coerces to true. But that is not needed. Unless I am missing something, this should be:

expression ? <Results fiftyFifty = "You win!"/> : <Results fiftyFifty = "You lose!" />

That makes more sense. You are just using a ternary expression. If it’s true, evaluate to the first one, if not return the second one. Does that make sense?

But to me that isn’t DRY enough. This makes more sense to me:

<Results fiftyFifty = { expression ? "You win!" : "You lose!" } />

I’m doing this off the top of my head, but that looks a lot cleaner.

Keep in mind that the hints are just user generated content and aren’t monitored very well. Some of them flat out don’t work. Take them with a grain of salt.

1 Like

Thanks for the explanation. I thought I was the only one facing this confusion.

Not at all. Everyone struggles. Even as you become a better developer, the coding challenges you face will get more difficult so you will still struggle. But that is what makes it fun. The point isn’t to get so good that you never struggle. The point is to learn from your struggles so you can move onto other, more interesting challenges.

2 Likes