maze maze - 3 months ago 18
React JSX Question

Change checked attribute of controlled checkbox (React)

I am new to React and am probably lacking the correct terminology to find a solution to my problem. It cannot be that hard.

I am building a simple app which displays a set of questions, one question at a time. After answering one question, the next question is shown.

I have a component

Question
that renders 3 checkboxes, each checkbox represents one possible
answer
to the Question.

{this.props.question.answers.map((answer, index) => {
return (
<li className="Question__answer" key={answer.id}>
<label className="Question__answer-label">
<input
className="Question__answer-checkbox"
type="checkbox"
value={index}
onChange={this.props.setAnswer}
defaultChecked={false} />
{answer.answer}
</label>
</li>

...

<button className="Question__next" type="button" onClick={this.props.onNext} disabled={this.props.isDisabled}>
Next question
</button>
)
})}


Inside my main component
Quiz
I call the component like this:

<Question step={this.state.step} question={this.state.questions[this.state.step]} setAnswer={this.setAnswer} onNext={this.onNext} isDisabled={this.isDisabled()} />


onNext
is my function which increments
this.state.step
in order to display the next question:

onNext(event) {
this.setState({step: this.state.step + 1});
}


Everything works fine, except: When the next question is displayed, I want all 3 checkboxes to be unchecked again. Currently they remember their checked state from the previously answered question.

Answer

So the thing is that React renders its components such that only the components that changed are rendered. Since nothing has changed about the checkboxes checked attribute after rerendering they stay in their previous state.

What you should do is toggle the checkbox state on click in the setAnswer function and pass this as a prop to the Question component.

Something like

this.state {
   checkedAttr: ["false", "false", "false"]
} 

Pass it on like

<Question step={this.state.step} question={this.state.questions[this.state.step]} setAnswer={this.setAnswer} onNext={this.onNext} isDisabled={this.isDisabled()} checkedAttr={this.state.checkedAttr} />

Use them in the checkboxes state as

{this.props.question.answers.map((answer, index) => {
  return (
    <li className="Question__answer" key={answer.id}>
      <label className="Question__answer-label">
        <input
          className="Question__answer-checkbox"
          type="checkbox"
          value={index}
          checked={this.props.checkedAttr[index]}
          onChange={this.props.setAnswer}
          defaultChecked={false} />
        {answer.answer}
      </label>
    </li>

    ...

    <button className="Question__next" type="button" onClick={this.props.onNext} disabled={this.props.isDisabled}>
        Next question
      </button>
  )
})}

In the onNext function just reset the states checkedAttr to false.

Comments