Как повторно запустить проверку при отправке в окончательной форме React

После проверки полей формы отправка не вызывает повторного запуска проверки. Есть ли способ вызвать повторный запуск проверки при отправке формы?

У меня есть поле формы, значение которого может стать недействительным, если оно не отправлено в течение определенного периода времени. Это не асинхронный режим; Я просто пытаюсь охватить сценарий, в котором пользователь какое-то время не нажимает кнопку «Отправить», а когда они в конечном итоге это сделают, значение станет недействительным. Окончательная форма запоминает результат проверки, которая происходит сразу после изменения значения, что означает, что неизмененное значение остается действительным независимо от того, сколько времени проходит между проверкой и отправкой. Это то поведение, которое я хочу изменить; промежуточное время имеет значение в моем случае использования. Я пробовал использовать прослушиватель beforeSubmit из пакета final-form-submit-listener, но он дает доступ только к объекту FormApi. Я пробовал использовать функции pauseValidation и resumeValidation из FormApi, но они не смогли достичь того, чего я хочу, или, возможно, я использую их неправильно. У меня такое ощущение, что это до боли очевидно, как это сделать, но я не могу этого понять. ????

Я создал эту песочницу, чтобы продемонстрировать, что я иметь в виду.

Спасибо!

ОБНОВЛЕНИЕ. Дополнительная информация:

  • Это на время. Если вы выбираете время на сегодня, вы можете выбрать время через 15 минут. Это действительно сейчас, потому что это в настоящее время в будущем. Если вы не касаетесь формы в течение следующих 20 минут, а затем нажимаете кнопку «Отправить», отправка должна быть предотвращена, потому что выбранное вами время теперь на 5 минут раньше.
  • Я подумал о том, чтобы просто добавить проверку прямо в обработчик отправки. Вот два ответа. Однако для меня это не идеально, потому что Final Form не принимает ошибки и не передает их объекту meta для полей формы. Моя кодовая база сложна и сильно зависит от объекта meta для отображения сообщений об ошибках. Попытка воспроизвести эту функциональность в обработчике отправки может сработать, но это хакерский метод и противоречит соглашениям, используемым во всей кодовой базе.

person Uche Ozoemena    schedule 11.07.2019    source источник
comment
Если это подтверждено один раз, зачем проводить повторную валидацию?   -  person its4zahoor    schedule 11.07.2019
comment
@ its4zahoor Как я уже сказал выше, в моем варианте использования промежуточное время имеет значение. Значение может стать недействительным через некоторое время, поэтому я хочу убедиться, что оно проверяется непосредственно перед отправкой.   -  person Uche Ozoemena    schedule 11.07.2019
comment
Хорошо, покажи песочницу   -  person its4zahoor    schedule 11.07.2019


Ответы (5)


Автор библиотеки здесь. Меня всегда восхищают новые способы опровергнуть мои предположения. Я имею в виду это искренне положительно, так как это приводит к обучению.

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

Если у вас есть лучшее / более простое / «более официальное» решение, я все равно хотел бы его увидеть!

Для этой задачи не нужны мутаторы или декораторы.

Более официальный способ сделать это - запустить проверку (можно даже повторно использовать this.validate) в onSubmit. Единственная сложность заключается в том, что ошибка вернется как meta.submitError, поэтому вам нужно проверить оба при отображении ошибки. Вот так:

 Изменить принудительную повторную проверку при отправке (React Final Form)

person Erik R.    schedule 12.07.2019
comment
Очаровательный! Я даже не подумал заглянуть в submitError. Сначала я реализую это в своем реальном коде, чтобы убедиться, что он работает так, как я ожидал. Большое спасибо! - person Uche Ozoemena; 12.07.2019
comment
Это приводит к избыточному коду для каждого компонента. Свойство validateOnSubmit было бы удобно. - person Steven Vachon; 20.10.2019
comment
Некоторая проблема взаимодействия с пользователем с предлагаемым решением: это не будет отображать сообщение об ошибке встроенного поля, если вы просто нажмете на submit, а другие поля уже содержат ошибки, поскольку код onSubmit не будет запущен - person Braulio; 09.01.2020

Вы уже помещаете функцию внутрь onSubmit, почему бы просто не добавить к ней нужные вам функции? event.preventDefault(), а затем работайте со своей функцией проверки, она является частью компонента и доступна вам.

handleOnSubmit(e){
  let value = document.querySelector("input").value 
  if (!!this.validate(value)){
    e.preventDefault();
    alert("Prevented submit event")
  } else{
    alert("Form submitted")
  }
}

теперь просто используйте эту функцию в форме onSubmit prop (я добавил бота, так как не был уверен в структуре компонентов):

<Form onSubmit={this.handleOnSubmit}>...</Form>
<form onSubmit={this.handleOnSubmit}>

И удалите декоратор submitListener из компонента формы:

decortaor={submitListener}

Теперь он проверит валидацию перед отправкой и предотвратит ее, если она не будет подтверждена.

person aviya.developer    schedule 11.07.2019
comment
Ой, извините, только что заметил, что я передаю ту же кнопку формы, чтобы отправить ввод в проверку, поэтому позвольте мне исправить это, найдя требуемый элемент - person aviya.developer; 11.07.2019
comment
также я не вижу объявления handleSubmit в вашем файле - person its4zahoor; 11.07.2019
comment
Да, он / она просто использует стрелочную функцию в опоре onSubmit, я предположил, основываясь на уже показанном коде, что для них дано это поставить. Но все равно добавлю к ответу. - person aviya.developer; 11.07.2019
comment
Да, @ aviya.developer, в реальном коде есть реальный обработчик, я использовал только простую стрелочную функцию для песочницы. Дай мне попробовать и посмотреть. - person Uche Ozoemena; 11.07.2019
comment
Проблема в том, что у него есть Form компонент, который принимает onSubmit стрелочную функцию, НО на самом деле form имеет onSubmit={handleSubmit}, который передается, но не объявляется. - person its4zahoor; 11.07.2019
comment
@UcheOzoemena Я немного не понимаю, откуда взять фактическое входное значение, может быть, вам будет легче получить его с помощью кода? - person aviya.developer; 11.07.2019
comment
@UcheOzoemena, обновите свою песочницу, когда исправите проблемы. Плюс будьте немного конкретны, основывается ли проверка на времени или стоимости? краткий пример использования поможет нам понять - person its4zahoor; 11.07.2019
comment
@ aviya.developer Я передаю this.validate подпорке validate Field. Таким образом, Final Form передает входное значение в this.validate. Что касается самого Form, в моем коде это фактически значения формы, которые передаются обработчику отправки, а не объект события. Я считаю, что Final Form делает preventDefault() автоматически, поэтому вы можете делать все, что захотите, в обработчике отправки, не беспокоясь об этом. - person Uche Ozoemena; 11.07.2019
comment
@ its4zahoor он основан на обоих. Это средство выбора времени, и если вы выбираете время на сегодня, вы можете выбрать время через 15 минут. Это действительно сейчас, потому что это в настоящее время в будущем. Если вы не прикасаетесь к форме в течение следующих 20 минут, а затем нажимаете кнопку «Отправить», отправка должна быть предотвращена, поскольку выбранное вами время теперь прошло на 5 минут раньше. - person Uche Ozoemena; 11.07.2019
comment
Итак, @ aviya.developer, что ваш метод действительно приходил мне в голову раньше, но я не использовал его из-за того, что я теперь подтвердил. По сути, проблема в том, что он находится вне опоры validate, поэтому Final Form не принимает ошибки и передает их объекту meta для полей формы. Моя кодовая база сложна и сильно зависит от объекта meta для отображения сообщений об ошибках. Попытка воспроизвести эту функциональность в обработчике отправки может сработать, но это хакерский метод и противоречит соглашениям, используемым во всей кодовой базе. - person Uche Ozoemena; 11.07.2019
comment
@UcheOzoemena Является ли meta ответственным за сообщение об ошибке, отображаемое под кнопкой отправки при ошибке? Потому что у меня это работает в песочнице кода. - person aviya.developer; 11.07.2019
comment
@UcheOzoemena вот вилка с моими изменениями: codeandbox.io / s / - person aviya.developer; 11.07.2019
comment
@ aviya.developer yes meta отвечает за сообщение об ошибке, отображаемое под полем ввода. Посмотрите на строку 110 в моей исходной песочнице. - person Uche Ozoemena; 11.07.2019
comment
Ваша песочница работает так, как я ожидал, но, как я уже сказал, она не работает с meta. Здесь это важно. - person Uche Ozoemena; 11.07.2019
comment
@UcheOzoemena Хорошо, тогда я потерял тебя на этом. Ошибки отображаются в соответствии с ожидаемым поведением. Не уверен в других мета-функциях, которые могут вам понадобиться. Должна ли мета делать что-нибудь еще? - person aviya.developer; 11.07.2019
comment
Лол, все в порядке, и эта ветка становится слишком длинной. Вчера я создал проблему для этого на GitHub. Подожду пока ответит автор проекта. Тем не менее, спасибо за ваши усилия! Я поддержу оба ваших ответа. :-) - person Uche Ozoemena; 11.07.2019

Итак, я нашел способ сделать это! ???? Я использую мутатор и использую его changeValue функцию для "изменить" значение соответствующего поля (я указываю то же значение). Это, в свою очередь, уведомляет все соответствующие стороны об изменении состояния формы, и запускается проверка. Ключ состоит в том, чтобы вызвать мутатор внутри обработчика отправки, который, таким образом, обеспечивает выполнение проверки при отправке формы. Взгляните на эту новую песочницу.

Соответствующие биты следующие:

// this is a stateful component
...
...
  mutateValue([name], state, { changeValue }) {
    // change the value to the same value, thus
    // triggering a revalidation of the same value
    changeValue(state, name, value => value);
  }

  handleSubmit(values) {
    alert("submitted");
  }

  render() {
    return (
  ...
  ...
        <Form
          onSubmit={this.handleSubmit}
          mutators={{ mutateValue: this.mutateValue }}
          render={({
            handleSubmit,
            form: {
              mutators: { mutateValue }
            }
          }) => {
            const mutateBeforeSubmit = values => {
              // supply the name of the relevant form field
              mutateValue("revalidate");
              // submit handler gets called if revalidation still passes
              handleSubmit(values);
            };
            return (
              <form onSubmit={mutateBeforeSubmit}>
              ...
              ...
              </form>
            );
          }}
        />
        ...
        ...

И поскольку он запускает тот же механизм проверки, meta используется соответственно!

Если у вас есть лучшее / более простое / «более официальное» решение, я все равно хотел бы его увидеть!

person Uche Ozoemena    schedule 12.07.2019

Поскольку вы хотите принудительно выполнить повторную проверку ИЛИ остановить отправку формы на основе interval, почему бы не использовать disabled при кнопке отправки?

// interval less than 900 = 15 minutes
<button type="submit" disabled={this.state.interval>=900}>
    Submit
</button>

Я также читал документы react-final-form, но я думаю, что это проще, если у вас нет конкретного случая, который нужно решить с помощью meta.

person its4zahoor    schedule 11.07.2019
comment
Обновлено :-). Я подумал об изменениях, которые он создает автоматически: / - person its4zahoor; 11.07.2019
comment
Да, это препятствует отправке, но, к сожалению, имеет ту же проблему, что и решение @ aviya.developer. Это не работает с meta; Мне нужно подходящее решение. - person Uche Ozoemena; 11.07.2019
comment
meta? можешь немного уточнить мету? ты о meta tags - person its4zahoor; 11.07.2019
comment
О нет, не мета-теги, лол. Это объект, предоставляемый каждому Field компоненту - см. Документацию здесь github.com/final -form / react-final-form # fieldrenderprops. Вчера я создал проблему для этого на GitHub. Подожду пока ответит автор проекта. Тем не менее, спасибо за ваши усилия! Я поддержу твой ответ. :-) - person Uche Ozoemena; 11.07.2019
comment
react-final-form содержит подробную документацию с примерами в песочнице. Я играл с ними. Спасибо, я скоро могу использовать react-final-form в своих проектах. - person its4zahoor; 12.07.2019
comment
Отлично! Да, это здорово. Я только что опубликовал решение, которое придумал. Посмотри. :-) Он отлично сочетается с meta, так что я доволен. :-D - person Uche Ozoemena; 12.07.2019
comment
Только что увидел ваше обновление ответа. Да, это еще одна хорошая идея, но она не предлагает способа оставить сообщение об ошибке с помощью meta. Эта meta часть является ключевой, и это происходит только тогда, когда вы подключаетесь к механизму проверки Final Form. Мое решение прекрасно с этим справляется. :-) - person Uche Ozoemena; 12.07.2019

Есть еще один вариант использования, когда требуется ручная проверка запуска: в этом случае мы получили форму ученика, в случае, если у нас есть новый ученик, поле под названием временный пароль должно быть заполнено, если нет, это поле не обязательно, чтобы было проще, мы обновляем схему проверки на лету (у нас был аналогичный случай с проверкой, которую нужно было включать всякий раз, когда какая-либо операция выборки была завершена).

Мы применили @ uche-ozoemena, и он работал нормально, но @ erik-r считается ли это решение взломом или мы можем использовать его в качестве одобренного обходного пути в сценариях, где нам нужно вручную запускать проверки?

Получилось что-то вроде (с использованием fonk-final-form):

  React.useEffect(() => {
    if (isUserCreation) {
      const newDataFormvalidationSchema = {
        ...dataFormvalidationSchema,
        field: {
          ...dataFormvalidationSchema.field,
          temporaryInitialPassword: [
            ...dataFormvalidationSchema.field.temporaryInitialPassword,
            Validators.required,
          ],
        },
      };

      dataFormValidation.updateValidationSchema(newDataFormvalidationSchema);
    }
  }, [isUserCreation]);

  return (
    <Form
      initialValues={initialData}
      mutators={{ mutateValue: mutateValue }}
      onSubmit={values => {
        save(values);
      }}
      validate={dataFormValidation.validateForm}

person Braulio    schedule 09.01.2020