redux-form: checkbox doesn't set `checked`, changes value between true/false

I’m a little confused by how checkboxes and radio buttons work in the example. On the simple example: https://erikras.github.io/redux-form/#/examples/simple

Checking Employed checkbox just sets the input’s value="true". Unchecking sets it to value="false". I believe it should leave value alone and instead add the checked property to the input. On the radio buttons, checked is never set.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 7
  • Comments: 28 (3 by maintainers)

Most upvoted comments

sex value is always true

The checked is being set in the code.

<input type="radio" {...sex} value="male" checked={sex.value === 'male'}/> 

You might have a good argument against setting value for a checkbox, but redux-form can’t know what kind of input it is until it receives an event. However, is there really a use case for needing a non-boolean value on a checkbox?

This is how I handled this with material-ui checkbox element:

<Checkbox checked={terms.value} onCheck={(e, checked) => terms.onChange(checked)} />

For semantic-ui-react, what I have done is

      <Checkbox
        {...input}
        value={input.value ? 'on' : 'off'}
        onChange={(e, { checked }) => input.onChange(checked)}
        {...custom}
      />

The values change to true or false state.

Thank you @erikras 😃 I’d like to bring attention on this line:

checked={this.props.input.checked}

Because before, I used:

checked={this.props.input.value}

It was working well in development mode, but not in production mode (minimified code, no webpack server, with webpack dll plugin). Still don’t know why, But using props.input.checked and OnChange binding made it work… I think more investigation is needed here…

Also +1 for the answer from @dbismut. In case anyone was interested, I wrapped the Material UI checkbox by my own component:

import React from 'react';
import MaterialCheckbox from 'material-ui/lib/checkbox';

export default (props) => {
  let newProps = Object.assign({}, props, {
    value: null,
    checked: props.value,
    onCheck: (e, checked) => props.onChange(checked)
  });
  return <MaterialCheckbox {...newProps} />
};

You can use this component the same way like other inputs:

<Checkbox label="Terms & conditions" {...terms} />

I found those two issues #2922 #1993 and added the attribute normalize={value => !!value} to my Field tag and it seems to solve it.

I agree that checking boxes should flip the checked property, not the value. In normal HTML posts, having a value of true or false has no bearing on if the form is submitted. Its the checked property that determines this.

Also groups of checkboxes are pretty common. Instead of each checkbox having its own name, they should be able to share a name. (group:option1, group:option2 over option1:true, option2:false). This can already be done with radio groups. But since the value is overwritten with true/false, this is impossible.

Finally, using true/false to determine checked/unchecked makes using the intermediate property awkward.

Keep in mind that you have complete control over how the values are passed from the redux-form field to your input component. i.e. you don’t have to do {...myField}, but you can pass each attribute separately, as long as you pass value and onChange, that’s all that redux-form cares about. For example, say you had a bizarre checkbox component that insisted on using the string values 'yes' and 'no', but you wanted a boolean in Redux, you could do

<WeirdSwitch
  value={myField.value ? 'yes' : 'no'}
  onChange={value => myField.onChange(value === 'yes')}/>

Hello everybody. Thank you @tobice for your comment! I’ve manage to successfully make it work with v6 API. For people interested:

import React, {Component, PropTypes} from 'react';
import Checkbox from 'material-ui/Checkbox';

class CheckboxInput extends Component {

    onCheck (e, checked) {
        this.props.input.onChange(checked);
    }

    render() {
        return <Checkbox
            {...this.props.input}
            checked={this.props.input.checked}
            onCheck={this.onCheck.bind(this)}
        />;
    }
}

export default CheckboxInput;

And use it in your form like that:

import CheckboxInput from '../../CheckboxInput';

...

<Field name="checkbox" component={CheckboxInput} type="checkbox" label="checkbox"/>

Here’s is what I did with Semantic UI checkbox.

  1. Initialize the form field value as boolean.
reduxForm({
    form:'RegisterForm',
    initialValues: {
        acceptedTerms:false
    }
}
  1. Defined the checkbox component as below:
<Form.Field error={field.meta.invalid}>
     <Checkbox checked={field.input.value ? true : false} onChange={(e,item) => field.input.onChange(item.checked)} label={field.label} />            
</Form.Field>

Maybe MaterialCheckbox component has the function of onCheck to change the value, but other’s DIY Checkbox does’t work.

for example, like semantic-ui-react

<Checkbox
      label={rest.label}
      checked={!!input.value}
      onClick={(e, { checked }) => input.onChange(!checked)}
/>

the checked’s value should change