Emoless96
Emoless96

Reputation: 103

React js, set class based on value

I'm working on a quiz and I would like to make it so when the user clicks the correct answer it turns green if the user clicks the wrong answer it turns red.

This is what I got right now:

state = {
  answerClass: false,
};


handleVoting(answer) {
    if (answer == this.props.questions[this.props.questionIndex].answer) {
      this.setState({
        answerClass: 'green'
      });
    } else {
      this.setState({
        answerClass: 'red'
      });
    }

    var options = [];

    if (this.props.options) {
      for (var i = 0; i < this.props.options.length; i++) {
        options.push( < div className = {
            this.state.answerClass
          } >
          <
          img onClick = {
            this.handleVoting.bind(this, this.props.options.value)
          }
          src = {
            url
          }
          /></div > );
      }
    }

So this creates two image buttons for voting when I click on one of them I am sending a value to the handleVoting function that checks if the value clicked is the same as the answer to the question I am setting a state to the class name.

The issue with this is that if I click on the correct option both turn green and if I click on the wrong option it turns both red.

Upvotes: 1

Views: 576

Answers (1)

atengel
atengel

Reputation: 119

You're close! What's happening is that you are applying the same part of state to all buttons. All you need to do to fix this is have a separate part of state for each button. For this case, I would suggest an array to hold the state for each button. Then, you just need to pass the index of the option to your handleVoting function and use it to determine which part of the state to set.

Also, not sure if just copy/pasted incorrectly, but make sure that your state is assigned to the UI in a render method. I would also recommend using the map function when you are dynamically assigning an array.

See below...

state = {
  answerClasses: [],
};


handleVoting(answer, index) {
    if (answer == this.props.questions[this.props.questionIndex].answer) {
      let newAnswerClasses = this.state.answerClasses;
      newAnswerClasses[index] = 'green';
      this.setState({
        answerClasses: newAnswerClasses
      });
    } else {
      let newAnswerClasses = this.state.answerClasses;
      newAnswerClasses[index] = 'red';
      this.setState({
        answerClasses: newAnswerClasses
      });
    }
   }

render() {
    let options = this.props.options.map(function(option, i) {
       return (< div className = {
            this.state.answerClasses[i]
          } >
          <
          img onClick = {
            this.handleVoting.bind(this, this.props.options.value, i)
          }
          src = {
            url
          }
          /></div > );
    }.bind(this));
    return <div>{options}</div>

  }

EDIT for comment

state = {
  answerClasses: [],
};


handleVoting(answer, index) {
      let newAnswerClasses = this.state.answerClasses;
    if (answer == this.props.questions[this.props.questionIndex].answer) {
      newAnswerClasses[index] = 'green';
      this.setState({
        answerClasses: newAnswerClasses
      });
    } else {
      // for loop method
      for(let i=0; i < this.props.options.length; i++) {
        if(this.props.options[i].value === answer) {
          newAnswerClasses[i] = 'red';
          break;
        }
      }
      // OR passing index to component via props method
      newAnswerClasses[this.props.answerIndex] = 'green';
      newAnswerClasses[index] = 'red';
      this.setState({
        answerClasses: newAnswerClasses
      });
    }
   }

render() {
    let options = this.props.options.map(function(option, i) {
       return (< div className = {
            this.state.answerClasses[i]
          } >
          <
          img onClick = {
            this.handleVoting.bind(this, this.props.options.value, i)
          }
          src = {
            url
          }
          /></div > );
    }.bind(this));
    return <div>{options}</div>

  }

Upvotes: 2

Related Questions