New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[blur event] Why does handleBlur updates field value? #2768
Comments
I am also having an issue with Blur modifying the value of the field. The problem for me is that onBlur assumes that the event contains the current value - which is not true when you batch react updates and the form is updated via autocomplete. In this case the browser fires Making |
I am currently getting around this issue by calling the https://github.com/erikras/redux-form/blob/master/src/__tests__/reducer.blur.spec.js#L70 |
Another workaround is to use the parse (and / or possibly normalize) prop of Field to force the type value of that the blur action sets into state. In my case, redux-form was converting number values of my fields into strings, causing issues with custom react-numeric input fields. Line 99 of ConnectedField calls onChangeValue which "normalises" the value of the field using a function passed into the parse or normalize prop of ConnectField. In the absence of these functions being specified, the value seems to default to a string. For what's worth, this is all I passed into the parse prop:
For it's worth, I agree with OP that the value being changed on a blur event is an unexpected and unconventional side effect that should considered for removal unless there's a really good reason for it. |
@carlsverre I tried your workaround: @erikras any objections to removing the value from |
@shodanuk this is assuming that value is of another type but still correct. This may be true for fields that imitate Such field consists of multiple checkboxes. onBlur is emitted with |
As far as I can tell the fact that blur changes the value has been the case since the 0.7 release of the project (earliest reference I could find to setting an onBlur handler for any form component). You can see the code here: I don't see any issues or comments mentioning why the blur event does this in the entire history of the project. I briefly looked at almost every commit which touched any of the blur code. Would really appreciate a comment from @erikras on why Blur changes the value. |
Hmm... Blur changes the value to allow maximum flexibility in how the library is used. Can we be guaranteed that every single input that calls However, I definitely see why someone might want to only flip the <input {...props.input} onBlur={() => props.input.onBlur(undefined, true)}/> Or optionally one could pass a <Field name="firstName" component={renderInput} noUpdateOnBlur/> I don't think that stripping the current value-setting functionality out of |
I see. I think it would be straightforward for those components to implement something like:
Anyway. Maybe we shouldn't go as far as having a separate flag for Current behavior: Desired behavior: What do you think @erikras ? |
If current consumers of the library are depending on various forms of the existing onBlur behavior - it will be a lot safer/faster for us to add a new mode rather than modifying the existing behavior. In that case my vote is for supporting a second explicit parameter to the onBlur method. Possibly it should be an options parameter to make future upgrades non-breaking as well:
|
Is there any fix for this right now? I'm using parse/format and any onblur event causes the field to be emptied. |
@mereskin I could be misunderstanding you, but this is not true. Calling I must be misunderstanding the problem here. Can you re-explain? Or make a sandbox to demonstrate it? |
@erikras maybe that's only when I'll try to make a sandbox tonight. |
…ializing the form (#2835) * passing the last initialValues into initialize action if it is reinitializing the form * Added test related to #2809 * Removed meta.touched from FieldArray props (#2836) * Add props to the params documented in the field-level validations example (#2855) * Fix typo in docs/api/Field.md (#2864) * Improve SubmissionError docs (#2873) * Add a selector to get touched and visited props from state (#2859) * added a selector (getFormMeta) which retrieves the form.{$name}.fields slice from state * added documentation for getFormMeta selector * Fixed field-level validation reset bug (#2888) * deleteInWithCleanUp needs to check if there is a value in the state before deleting. (#2876) * deleteInWithCleanUp needs to check if there is a value in the state before deleting, to avoid Invalid KeyPath errors * Got rid of string compare * clean script - added es folder to be rimrafed before build (#2860) * Add a Field's initial value to props.meta.initial (#2858) * Add meta.initial to Field props for access to a field’s initial value. * es6 typo * add meta.initial to the docs for Field * Demonstrated that calling onBlur() does not change value #2768 * Better cleanup on UNREGISTER (#2889) * Checkbox default behavior proposal (#2863) instead true/false to be true/'' as the current true/false breaks pristine prop * Fancy new npm5 lock file! * Allow direct imports to reduce bundle size. (#2893) * Fix deep equal on maps with different structures (#2892) * Remove references to react-router from doc page. (#2898) * Add PropTypes for the Field components (#2862) * Add PropTypes for the Field components * Export fieldInputPropTypes, fieldMetaPropTypes and fieldPropTypes * Merged with changes from #2893 * Exports defaultShouldValidate and defaultShouldAsyncValidate (#2891) * Exports defaultShouldValidate and defaultShouldAsyncValidate These default functions are exported for external use - particularly so that a user can wrap the default functionality with specialised behaviour. To resolve #2890 * Export default shouldValidates in immutable wrapper * Allow direct imports to reduce bundle size. (#2893) * Fix deep equal on maps with different structures (#2892) * Remove references to react-router from doc page. (#2898) * Add PropTypes for the Field components (#2862) * Add PropTypes for the Field components * Export fieldInputPropTypes, fieldMetaPropTypes and fieldPropTypes * Merged with changes from #2893
I'm also struggling with the same problem, I prepared a sandbox here which shows the issue I have. In my case I have a select control whose values is a Object which I stringify and parse back to JSON in the field. The value of the form is first the selected one but then (on blur event) it gets reverted to the original value. Am I doing anything wrong? Are there any workaround? |
Looks like this issue is connected. |
@erikras I have created a sandbox below which shows a simple As a temporary fix I can put Sandbox: https://codesandbox.io/s/l5XOknk05 |
Fwiw, it seems to me that a |
@mlarcher is correct. Passing a NoOp function to
|
@mlarcher Looks like the downside of using e.preventDefault() is clearly explained in the documentation
Probably focus state is not important in your case, but still... |
Using event.preventDefault() was not working for me, since input.touched was then not set to true (this is needed in my case for displaying input error hints). I think this is related to what @An6r mentioned above. It's not pretty, but I ended up passing down a callback that invokes input.onBlur without the event (this also satisfies my TypeScript compilation). If anyone has a better solution I'd love to hear it.
|
Same problem here, we are using react-select which has controled, non-input |
Any progress on this issue? I think it is a consumer's responsibility to call onChange whenever he wants. But I do understand that we don't want to introduce a breaking change. So what about this flag @erikras was talking about. |
For now I am just manually dispatching blur action with current value
|
ant-design's InputNumber hits this problem. onChange handler of InputNumber is fed with a number value, however onBlur is fed with a raw FocusEvent dispatched from the HTMLInputElement underneath. onChange is called immediately before onBlur if the value is corrected by min-max validations. Maybe these two events occur in the same frame mentioned by @carlsverre , the value of InputNumber is always reverted by the raw value from FocusEvent unexpectedly. |
Cool! It works, But, for handling pristine also change input type to number. |
I'm still having this issue. "redux-form": "^7.0.4", |
Thanks, worked for me 👍 |
this action broke "asyncBlurFields"( |
|
I had the same issue with onblur and onfocusout, it change the input value to 'true' for some reason. |
What is the current behavior?
onBlur and onFocus callbacks are required to mark field as touched to display per-field validation. onBlur and onFocus assume DOM event is passed and current field value corresponds to value of the underlying DOM element.
That behavior is not working for custom components. If custom component is used in place of input the
value
property of DOM element that originates event can not be equal to that of a component itself.For example, we use
CheckBoxGroup
which hasvalue
property defined asarrayOf(string)
. This component still emits onFocus and onBlur events when individual checkboxes are checked/unchecked and passes DOM event through. This DOM event is used by blur, value is extracted from it and this value is no longer an array but stringtrue
, since this value is read fromchecked
property of a checkbox.What is the expected behavior?
onBlur event handler shouldn't update the value of the field and shouldn't assume that event object passed in is actually a DOM event. onBlur handler should update
touched
property of the field so that validation is still displayed.Is there any reason why onBlur event updates form state? Can we use
onChange
events exclusively to update form state?What's your environment?
All environments
The text was updated successfully, but these errors were encountered: