redux-form: Checkbox value breaking pristine state
Hi, I found out that using true/false value within checkboxes is breaking the pristine state value. The case is: Checkbox initial value is probably an empty string. When I set a checkbox to checked state and then uncheck it, the pristine value changes. The flow is ‘’ -> true -> false. You can even check it in the simple example here: http://redux-form.com/6.6.3/examples/simple/
I fixed it by using normalize prop in Field for checkbox component like: <Field normalize={value => value || ''} ... />
. Another approach could be setting default initial values for all the checkboxes in each form, which doesn’t make sense at all.
I propose to set as a default behavior true || ‘’ for checkboxes. Then the checkboxes will behave the same way as any other types of inputs.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 18 (7 by maintainers)
This seems like a very bad solution to the problem. If your checkbox is initialised with an empty string as the value, isn’t the problem this initial wrong value rather than any subsequent correct values?
Since this breaking change was released as a minor version you probably very silently broke most applications using checkboxes in redux-form. It certainly broke mine.
Not sure if intended, but this change now breaks the application I’m currently working on. I’m submitting boolean values from my form to an API which expects the relevant property to be an actual boolean value (
true
/false
).However, after this change, when I uncheck the box, it now submits an empty string while previously it submitted
false
. The API cannot convert the empty string to a boolean, so I’m getting an error.I can work around this by converting the value to an actual boolean before making the API call, or fixing it on the API-side. I’m not really liking either approach though, since it affects every checkbox value I use within the app.
This should be marked as breaking change. Parts of our application went down, without any notice. Also, i don’t see how this could make sense. This does not brake pristine, if you would use it with right initial values. Checkbox is not an input, where you could/should have value as a string. I hope this will be fixed in future versions!
Reverting to 6.6.3
Shouldn’t be this change marked as BC break? Suddenly my app stopped working after update.
Sure, there are plenty of workarounds to think of. I’m just not sure if the current default behaviour introduced by this change is really sensible.
It doesn’t feel right that something that worked like it should before (checkbox checked means a
true
value, unchecked is afalse
value), now requires additional code to make it work logically again. It’s also pretty easy to forget, causing any receiving system that expects an actual boolean value to break. Perhaps @erikras would like to chime in?Is there any way we can get the change introduced by this PR to work together with the previous behaviour?
@vitbokisch: I think you misunderstand why people are complaining as well as what we would prefer.
We’re not complaining from aches in our wrists from all the excessive writing we had to do. While I hadn’t wrapped the component, I only had to change something like 8 instances. This is not a matter of characters changed.
First of all, people are annoyed about a breaking change being released as a minor version. Maybe you work with a backend that treats
""
andfalse
as the same and thus nothing happened. I don’t. Frankly I prefer not to, as I wouldn’t consider them the same. Everyone complaining came here looking for answers to an inexplicable bug that suddenly manifested. It took me hours to even find this thread and I imagine it’s the same for many other people. How could I have avoided a suddenly broken app with a change in behaviour like this? Except of course by using shrinkwrap/lock-files, which I guess this whole thing is the perfect argument for.Secondly, no one argues for
""
->true
->false
being a good or logical pattern and no one wants pristine state to break for checkboxes. But to look at that trio and concludefalse
is the odd man out is baffling to me. The obvious pattern should befalse
->true
->false
. And no, this does not mean that you should have to initialise the value manually, the same logic resulting in the secondfalse
should result in the default value beingfalse
. Honestly, I think even""
->"on"
->""
would be a better pattern than this change, at least it would be obvious what was happening and use a consistant type.This change moves the so-called problem from people who use
''
as the initial value to people who usefalse
as the initial value. For example, if your initial value isfalse
, checking and then unchecking the checkbox moves the value fromfalse
totrue
to''
, which presumably causes the same issue withpristine
that the OP was concerned about.Regardless of whether
''
is a better unchecked value thanfalse
, this is a substantial change in behavior. Would you be willing to update the release notes for 6.7.0 to reflect this as a breaking change?As for the underlying
value
issue, perhaps there is room to make redux-form configurable withcheckedValue
anduncheckedValue
configurations to be used for all checkboxes?I still stand by the flow should be:
undefined
->{ "employed": true }
->undefined
if no initial values are set and ifinitalValues
is''
:{ "employed": '' }
->{ "employed": true }
->{ "employed": '' }
ifinitalValues
isfalse
:{ "employed": false }
->{ "employed": true }
->{ "employed": false }
Yes, at the DOM level, an attribute can only have a false value by having an empty string. But as @vitbokisch points out this is reconciled by the fact that in plain HTML forms, empty strings are ignored. In redux-form the equivalent of an ignored value is that it’s key doesn’t even exist in the form values.
EDIT: 7.0’ s default behaviour for uninitialized values was even better after reading that long discussion:
undefined
->{ "employed": true }
->{ "employed": false }
.Published fix in
v7.1.0
.@dmeenhuis if it worked before and you use Field component, you can just use the opposite approach I’ve been using (I mean using normalize). Could work like this:
Also using props
parse
orformat
may help.