-
Notifications
You must be signed in to change notification settings - Fork 24
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
[1.6.7] Side-effect in Firefox / Form.validateField method #372
Comments
Hello, @CugeDe. Thanks for reporting the issue!
There are two types of field updates that may happen:
Validation itself may also happen in both of these ways above. For example, usually validation is performed using the first update type, and operates on the existing field state. This allows to make validation calls debounced while having synced value updates of a field while typing (otherwise a debounced validation call would execute with the obsolete state of a field, a state when the validation call was dispatched). And it may also happen using the second update type, operating on the explicit field state. This happens during reactive props resolving, where a subsribed property of a field state resolves and must be validated at the same time. Regarding to your issue
Thanks. |
Hello @kettanaito. Thanks for answering! If I understand,
import React, { Component } from 'react';
import { createField } from 'react-advanced-form';
import { Label, FormGroup, FormFeedback } from 'reactstrap';
import PropTypes from 'prop-types';
import ReactSelect from 'react-select';
const styles = {
multiValue: (base, state) => {
return state.data.isFixed ? { ...base, backgroundColor: 'gray' } : base;
},
multiValueLabel: (base, state) => {
return state.data.isFixed ? { ...base, fontWeight: 'bold', color: 'white', paddingRight: 6 } : base;
},
multiValueRemove: (base, state) => {
return state.data.isFixed ? { ...base, display: 'none' } : base;
}
};
class Select extends Component {
static propTypes = {
label: PropTypes.string,
options: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.oneOfType([
PropTypes.string.isRequired,
PropTypes.number.isRequired
]),
label: PropTypes.string.isRequired,
}),
).isRequired,
}
/* Handler for "react-select" onChange event */
handleChange = (selectedOption, { action, removedValue }) => {
/* Dispatching "react-advanced-form" field change handler to update the field record */
switch (action) {
case 'remove-value':
case 'pop-value':
if (removedValue.isFixed) {
return;
}
break;
default:
break;
}
this.props.handleFieldChange({ nextValue: selectedOption });
}
getFieldErrors(asyncErrors, field) {
let errors = false;
if (asyncErrors && asyncErrors[field] && asyncErrors[field].errors) {
errors = asyncErrors[field].errors;
}
return errors;
}
render() {
const { fieldProps, options, fieldState, name, label, asyncErrors } = this.props;
var { errors } = fieldState;
var customErrors = this.getFieldErrors(asyncErrors, name);
if (customErrors) {
if (!errors)
errors = [];
customErrors.forEach(error => {
errors.push(error);
});
}
return (
<FormGroup row>
{ label &&
<Label for={ name } className="col-12 align-self-center mb-0">{ label }</Label>
}
<div className="col-12">
<ReactSelect {...fieldProps} isClearable={!options.some(v => !v.isFixed)} styles={styles} onChange={this.handleChange}/>
{errors && errors.map((error, index) => (
<FormFeedback key={index} className="d-block">{error}</FormFeedback>
))}
</div>
</FormGroup>
)
}
}
export default createField({
serialize(selectedValue) {
if (Array.isArray(selectedValue)) {
return selectedValue.map((element, idx) => { return element.value; });
}
else
return selectedValue.value;
},
enforceProps({ props: { options, isMulti } }) {
/* Declare which props to propagate from "<Select>" props to "fieldProps" */
return {
options,
isMulti,
}
},
})(Select) Thanks. |
Thank you for a fast reply. Yes, Strangely enough, your sandbox works as expected when I test it on Firefox (66.0.2 x64) and Chrome (73.0.3683.86 x64). To narrow down the problem, could you please assist me in this questions:
/* Handler for "react-select" onChange event */
handleChange = (selectedOption, { action, removedValue }) => {
/* Dispatching "react-advanced-form" field change handler to update the field record */
switch (action) {
case 'remove-value':
case 'pop-value':
if (removedValue.isFixed) {
return;
}
break;
default:
break;
}
this.props.handleFieldChange({ nextValue: selectedOption });
} When the I really doubt that there is a bug in such fundamentals (although I don't deny it entirely), respective tests seems to pass successfully. Unfortunately, I can't test it on a Linux distributive right now. Maybe it's somehow related to the environment/browser. To be honest, I'm not sure at this point what is the cause of the issue. |
Hello, I was able to reproduce the exact same bug with the code sandbox provided by using Google Chrome 73.0 on Android 8.0. When selecting a value on my mobile, the select is not updated. I tested it with only react-select without React-advanced-forms, and it's working as expected. EDIT : As we can see, when we try to select a value in the HTML5 select, the value is selected and then unselected automatically (visually) but if we submit the form the selected value is returned. By the way in the BasicSelect field (html5 select), the onChange event is not called. My implementation of html5 select is probably the issue though. |
Your questions
const styles = {
multiValue: (base, state) => {
return state.data.isFixed ? { ...base, backgroundColor: 'gray' } : base;
},
multiValueLabel: (base, state) => {
return state.data.isFixed ? { ...base, fontWeight: 'bold', color: 'white', paddingRight: 6 } : base;
},
multiValueRemove: (base, state) => {
return state.data.isFixed ? { ...base, display: 'none' } : base;
}
}; Programmatically removing these fixed values is still possible. Doing it in this.props.handleFieldChange({ nextValue: selectedOption }); MoreThe fact that you are grabbing the value from the field to update the field value in the form makes me think that there could be an event triggered too early or too late in the 'change' event processing. @BrandonGillis, got the same on your codesandbox. |
Thank you both for providing more details. In case it's a concurrency issue, there is a high change it will be solved by #354, on which I'm working at the moment. Expect the next minor release somewhere in April (sorry, I don't have time to dive into it earlier). |
Testing environment
What
Current Behaviour
createField
) and usingReact-Select
component. This select field is multiple.Expected Behaviour
Investigation result
Form.validateField
is called (line 488).See here
Here,
forceProps
is alwaysfalse
.On Chrome:
On Firefox:
More
I was not able to reproduce the problem on Debian unstable (my only other testing environment).
Here's a code sandbox (See here) showing the bug I have on Archlinux with Firefox.
On the sandbox, I can't even select a single value and the bug also happens when the
isMulti
=false
.Resolution
I don't really understand why you are using
R.path(explicitFieldProps.fieldPath, fields)
.I tried removing the line and it works (same as setting forceProps to
true
).The text was updated successfully, but these errors were encountered: