#reactjs #formik
#reactjs #formik
Вопрос:
Formik имеет две опции, определяющие, когда происходит проверка: validateOnChange
и validateOnBlur
.
Проблема с использованием validateOnChange
— пользователь будет получать ошибки при вводе, скажем, электронной почты — потому что это недопустимо, когда вы только начали вводить первые буквы.
В случае validateOnBlur
— допустим, пользователь ввел неверное электронное письмо, покинул поле, вернулся и исправил на правильное электронное письмо — ошибка будет отображаться в любом случае, пока они не покинут поле, так что это также не работает для меня.
Чего я хотел бы достичь — впервые проверить поле на blur
и начиная с этого момента — на change
.
Каждое поле должно обрабатываться индивидуально.
Я пытался найти собственные способы сделать это, но не смог найти ни одного, поэтому я придумал это решение, которое мне не очень нравится, потому что оно не безупречно:
TL;DR:
Я переопределяю стандартные onBlur
и onChange
исходящие из Field
реквизитов и а) onBlur
отмечаю поле как измененное один раз (возможно, я мог бы использовать touched
здесь) б) onChange
Я проверяю, было ли поле затронуто один раз, и если да — вызываю проверку.
0) Отключить проверку
<Formik
validateOnChange={false}
validateOnBlur={false}
...
1) Добавлено changedFields
в мое состояние
public state: IState = {
changedFields: {}
};
2) Используйте специальный метод, который переопределяет значение по умолчанию onBlur
и onChange
<Field name="userName" render={(props: FieldProps<MyFormInterface>) => (
<input type="text" label={'Name'} {...formikCustomValidation(props, this)} />
)}/>
3) Метод. Передача реквизитов поля и родительского компонента, в котором находится состояние с changedFields
.
function formikCustomValidation({ field, form }: FieldProps, ownerCmp: Component<any, any>) {
return {
...field,
onBlur: e => {
if (field.value !== form.initialValues[field.name]) {
ownerCmp.setState({
changedFields: {
...ownerCmp.state.changedFields,
[field.name]: true
}
});
}
field.onBlur(e);
setTimeout(form.validateForm);
},
onChange: e => {
field.onChange(e);
if (ownerCmp.state.changedFields[field.name]) {
setTimeout(form.validateForm);
}
}
};
}
Вопрос в том, есть ли способ сделать это проще?
Проблема с этим решением — если я отправляю нетронутую форму и появляются некоторые ошибки — значение фокусировки и исправления не помечает поле как действительное — потому что это первое «касание», а поле все еще находится в статистике, ожидающей первого состояния размытия, которое должно заставить прослушивать «изменения».
В любом случае, поддерживать это может быть непросто, поэтому ищите лучшее решение. Спасибо!
Комментарии:
1. Разве это не поведение по умолчанию? Просто не устанавливайте
validateOnChange
иvalidateOnBlur
, и Formik будет делать то, что вы описываете.2. О, я не могу поверить, что пропустил это. Спасибо, приятель.