I am having a very annoying issue with React and checkboxes. The application I am working with requires a list of checkboxes that represent settings that are persisted in the back-end. There is an option to restore the settings to their original state.
At first, I created a component that has an object like a map of settings. Each setting has a key and a boolean value. Hence:
{
bubbles: true,
gregory: false
}
Is to be represented as:
<input type="checkbox" value="bubbles" checked="checked" />
<input type="checkbox" value="gregory" />
Now, it seems React is ignorant about how a checkbox is supposed to work. I don't want to set the checkboxes' values, I want the "checked" property.
Yet, if I try something like this:
<input
type="checkbox"
value={setting}
checked={this.settings[setting]}
onChange={this.onChangeAction.bind(this)}
/>
I get this warning:
Warning: AwesomeComponent is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: [some useless docs page I read several times to no avail]
So I decided to create another component to wrap each individual checkbox and I got this:
<input
type="checkbox"
checked={this.state.checked}
onChange={this.onChangeAction.bind(this)}
/>
Now the checked
is a property present directly in my state.
This yields the same warning, so I tried using defaultChecked
:
<input
type="checkbox"
defaultChecked={this.state.checked}
onChange={this.onChangeAction.bind(this)}
/>
Which makes the warning disappear, but now it is unable to reset the checked
value to the default one. So I tried playing with the method componentWillReceiveProps
, this way I am quite sure my state is correct, this.state.checked
is correct and the component renders again.
And it does. But the checkbox remains as it was originally.
For now I left that ugly warning and I am using checked
.
How do I fix this thing so the warning goes away?
I was thinking that perhaps there is a way to force-re-render the component, so it captures the new defaultChecked
value and uses it. But I don't know how to do that. Perhaps suppress the warning only for this component? Is that possible? Perhaps there is something else that can be done?