Как настроить логику отображения ошибок в Formik? - PullRequest
0 голосов
/ 21 апреля 2019

Formik имеет две опции, управляющие временем проверки: validateOnChange и validateOnBlur.

Проблема с использованием validateOnChange - пользователь получит ошибки, когда они начнут печатать, скажем, электронную почту - потому что это недопустимо, когда вы только начали вводить первые буквы.

В случае validateOnBlur - скажем, пользователь ввел неправильный адрес электронной почты, оставил поле, вернулся и исправил правильный адрес электронной почты - ошибка будет отображаться в любом случае, пока они не покинут поле, поэтому это также не работает для меня.

Чего я хотел бы добиться - впервые проверить поле на blur и начать эту точку - на change.

Каждое поле должно пройти это лечение индивидуально.

Я пытался найти нативные способы сделать это, но не смог найти ни одного, поэтому я придумал это решение, которое мне не очень нравится, потому что оно не безупречно:

TL;DR: Я переопределяю стандартные onBlur и onChange, исходящие от реквизита Field и a) onBlur - помечаем поле как измененное один раз (вероятно, я мог бы использовать touched здесь) b) 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) Способ. Передача реквизита Field и родительского компонента, в котором находится состояние с 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);
      }
    }
  };
}

Вопрос - есть ли способ сделать это проще? Проблема с этим решением - если я отправляю и оставляю нетронутой форму, и появляются некоторые ошибки - значение фокуса и исправления не помечает поле как действительное - потому что это первое касание, а поле все еще находится в состоянии ожидания первого состояния размытия, которое предположительно заставить слушать «изменения».

В любом случае, поддержание этого может быть болезненным, поэтому ищите лучшее решение. Спасибо!

...