Boky Boky - 2 months ago 19
React JSX Question

Checkbox in react js doesn't change

I have main component as follows :

export default class RegistrationFormStepFour extends React.Component{
constructor(props){
super(props);
this.state = {
terms: false,
emailNotifications: false,
smsNotifications: false,
errors: {}
}
}


handleTerms(event){
event.preventDefault();
this.setState({terms: !this.state.terms});
}

render(){
const language = this.props.currentLanguage;

return (
<div>
<Terms
nameYes="chcTerms"
text={language.termsText}
state={this.state.terms}
onChange={this.handleTerms.bind(this)}
currentLanguage={language}
error={this.state.errors.terms}/>

</div>
);
}
}


And component term is as follows :

import React from 'react';

const Terms = ({nameYes, text, state, onChange, error}) => {

let hasError = error ? "hasError" : "";

return (
<div className="col-lg-12 text-center" style={{marginBottom: 30}}>
<form>
<label className="radio-inline">
<input
type="checkbox"
name={nameYes}
checked={state}
onChange={onChange}
value=""/>
</label>
</form>
<p className={`questionsText ${hasError}`} style={{marginTop: 10}}>{text}</p>
</div>
);
};

export default Terms;


But when I click on the checkbox, nothing happens. If I console log the
state
in the terms component it show right value. First time is
false
, when I click on the checkbox than is true, but the checkbox isn't checked.

Any advice?

Answer

The event.preventDefault() is causing your problems in the controlled component checkbox.

http://www.matthiaslienau.de/blog/tags/checkbox

Checkboxes (and Radio Buttons): Manually updating state fails for checkboxes (and without having tested it: I think for radio controls as well). Why? The problem one will face is that the checkbox onChange event behaves in a special way since the era of HTML (how could I forget!): You may not toggle the state of a checkbox manually via the .checked property. Nor does React. The onChange (onClick) event is fired after the element state changed internally. This may just be reverted based on the return value of the event handler. See this post for a comprehensive examination of this fact.

const Terms = ({ nameYes, text, state, onChange, error }) => {
  let hasError = error ? "hasError" : "";
  return (
    <div>
      <form>
        <label className="radio-inline">
          <input
            type="checkbox"
            name={nameYes}
            checked={state}
            onChange={onChange} 
          />
        </label>
      </form>
      <p className={`questionsText ${hasError}`}>{text}</p>
    </div>
  );
};

class RegistrationFormStepFour extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      terms: false,
      emailNotifications: false,
      smsNotifications: false,
      errors: {}
    }
  }

  handleTerms(event) {
    this.setState({ terms: event.target.checked });
  }

  render() {
    const language = { termsText: 'Some Language' };
    return (
      <div>
        <Terms
          nameYes="chcTerms"
          text={language.termsText}
          state={this.state.terms}
          onChange={this.handleTerms.bind(this)}
          currentLanguage={language}
          error={this.state.errors.terms}/>
       {JSON.stringify(this.state)}
      </div>
    );
  }
}

ReactDOM.render(<RegistrationFormStepFour />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>