ReactJs Checkbox doesn't change value after first use

1.4k Views Asked by At

I have a large form with various form elements which is dynamically rendered from a get request. All other types of form (such as text and select) are working fine, however the checkbox is not.

After I check it once, it only stays on (even if I uncheck it), am I missing something or doing something wrong here?

Here is my current relevant code:

class Input extends Component{
    render(){
        var form;
        if (this.props.componentClass=="choice") {
            // select form
        }

        else if (this.props.componentClass=="bool")
            form =(<Checkbox id={this.props.controlId} onChange={this.props.onChange}
                               defaultChecked={this.props.placeholder} >
                        </Checkbox>);
        else
            // text form
        return (
            <div>
                <Form inline onSubmit={this.handleSubmit}>
                    <FormGroup controlId={this.props.controlId}>
                        <ControlLabel>{this.props.name}</ControlLabel>
                        {form}
                        <Panel>
                        {this.props.description}
                        </Panel>
                        <FormControl.Feedback />
                    </FormGroup>
                </Form>
                <br/>
            </div>
        );
    }
}

// onChange code (comes from a parent component)
    onChange(e){
        const form = Object.assign({}, this.state.form);
        form[e.target.id] = e.target.value;
        this.setState({ form });
        console.log('current state: ', this.state);
    }
3

There are 3 best solutions below

1
On BEST ANSWER

You must bind onChange function as said before, but you should use "checked" instead of "value".

Here is your example modified this way:

https://jsfiddle.net/8d3of0e7/3/

class Input extends React.Component{

    constructor(props){
    super(props)
    this.state = {form:{}}
  }

    render(){
    var form;
    if (this.props.componentClass=="choice") {
      // select form
    }else if (this.props.componentClass=="bool"){
      form = (
        <ReactBootstrap.Checkbox 
          id={this.props.controlId} 
          onChange={this.props.onChange.bind(this)}
          checked={this.state.form[this.props.controlId]}
          defaultChecked={this.props.placeholder} >
        </ReactBootstrap.Checkbox>);
    }else{
      // text form
    }
    return (
      <div>
        <ReactBootstrap.Form inline onSubmit={this.handleSubmit}>
          <ReactBootstrap.FormGroup controlId={this.props.controlId}>
            <ReactBootstrap.ControlLabel>
              {this.props.name}
            </ReactBootstrap.ControlLabel>
            {form}
            <ReactBootstrap.Panel>
              {this.props.description}
            </ReactBootstrap.Panel>
            <ReactBootstrap.FormControl.Feedback />
          </ReactBootstrap.FormGroup>
        </ReactBootstrap.Form>
        <br/>
      </div>
    );
  }

  componentDidUpdate(){
    console.log('current state: ', this.state);
  }

}

function onChange(e) {
  const form = Object.assign({}, this.state.form);
  form[e.target.id] = e.target.checked;
  this.setState({ form });
}

ReactDOM.render(
    <Input componentClass='bool' controlId='retired' 
    name='Is retired?' onChange={onChange}/>,
    document.getElementById('root')
)

In this example our state will be: state:{form:{retired:true}}

0
On

The issue is that you gave the checkbox an onChange without binding it to a value. Therefor, the initial check is working since that is what the defaultChecked is doing for you, but once you actually interact with it, you have no state bound to it causing react to not rerender it in the checked or unchecked position.

0
On
  const TermAndConditions = () => {
  const [checked,setChecked] = useState(false);

  return (
    <Wrapper>
      <CustomCheckbox
        type="checkbox"
        width="20%"
        checked={checked} // give checked value
        value={checked}
        onChange={e => setChecked(e.target.checked)}
      />
      <label>Agree term and conditions.</label>
    </Wrapper>
  );
};
export default TermAndConditions;