问题
I have the following redux form:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Field, reduxForm, getFormSyncErrors } from 'redux-form';
import { createExpense } from '../../actions';
import { validateName, validateImage } from '../../helpers/expense_utils';
import { renderInputField, validate, renderTextAreaField, renderDropzoneField } from '../../helpers/form_utils';
const validators = [
{
field: 'title',
validator: validateName
},
{
field: 'description',
validator: validateDescription
},
{
field: 'amount',
validator: validateAmount
},
{
field: 'image',
validator: validateImage
}
];
class NewExpense extends Component {
constructor(props) {
super(props);
this.state = {
error: undefined,
imagePreviewUrl: undefined
};
}
_onSubmit = values => {
let formData = new FormData();
formData.append('title', values.title);
formData.append('description', values.description);
formData.append('amount', values.amount);
formData.append('file', values.image[0]);
this.props.createExpense(formData, this.props.groupId, () => this.props.onClose(), error => this.setState({error: error}));
}
_onImagePreviewChange = files => {
//this.props.inputErrors.image is one step behind
this.setState({
imagePreviewUrl: files[0].preview
});
}
render() {
const { handleSubmit } = this.props;
const { imagePreviewUrl } = this.state;
return (
<div>
<form onSubmit={ handleSubmit(this._onSubmit.bind(this)) }>
<Field name="title" label="Name" type="text" component={ renderInputField }/>
<Field onChange={this._onImagePreviewChange.bind(this)} previewUrl={ imagePreviewUrl } name="image" label="Image" component={ renderDropzoneField } />
<button type="submit" className="btn btn-primary">Create</button>
<button type="button" className="btn btn-primary" onClick={this.props.onClose}>Cancel</button>
</form>
{ this.state.error ? <span>{this.state.error}</span> : <noscript/> }
</div>
);
}
}
export default connect(state => ({
inputErrors: getFormSyncErrors('NewExpense')(state)
}), { createExpense })(reduxForm({
validate,
form:'NewExpense',
validators
})(NewExpense));
I want to have access to the field-level errors of the form inside _onImagePreviewChange
, with inputErrors
I set inside mapStateToProps
.
The problem is that the validation functions runs after onChange
handler function. Therefore the error message is always stale. For example, if user select a file of disallowed type, the message would be undefined
, the next time if user selects an file of allowed type, this time it wouldn't be undefined
as an error was assigned to it in the previous step.
Why does this happen and how should I fix it?
回答1:
Validation can only run after some fields have changed and this is why the first time _onImagePreviewChange
is called with an invalid value, there are still no validation errors (as you said, validation is one step behind).
I would suggest to use componentWillReceiveProps
method and within this method access the next and the current validation errors, check if some error was fixed or generated and take the actions you need to take. For example:
componentWillReceiveProps(newProps) {
// here newProps.inputErrors is up-to-date while this.props.inputErrors is the current
if (newProps.inputErrors && newProps.inputErrors !== this.props.inputErrors) {
console.log(newProps.inputErrors); // up-to-date input errors
if (newProps.inputErrors.image) {
// clear invalid image field if you need to
this.props.change('image', '');
}
}
}
来源:https://stackoverflow.com/questions/49936192/redux-form-validation-runs-after-onchange-handler-function