繁体   English   中英

如何在 React Final Form 中提交时重新运行验证

[英]How to rerun validation on submit in React Final Form

一旦表单的字段被验证,提交不会触发重新运行验证。 有没有办法在提交表单时触发重新运行验证?

我有一个表单字段,如果未在特定时间范围内提交,其值可能会变为无效。 这不是异步的; 我只是想介绍一个场景,在这种情况下,用户有一段时间没有点击提交,当他们最终点击提交时,该值将变得无效。 最终表单会记住值更改后立即发生的验证结果,这意味着无论验证和提交之间经过多长时间,未更改的值仍然有效。 这是我想要挂钩和改变的行为; 在我的用例中,中间时间很重要。 我尝试使用final-form-submit-listener包中的beforeSubmit侦听器,但它只提供对FormApi对象的访问权限。 我尝试使用pauseValidationresumeValidation从功能FormApi但他们无法达到我想要的东西,或者也许我没有正确地使用它们。 我有一种感觉,如何做到这一点非常明显,但我无法弄清楚。 😩

我创建了这个沙箱来演示我的意思。

谢谢!

更新:一些附加信息:

  • 这是一个时间选择器。 如果您选择今天的时间,您可以选择从现在起 15 分钟后的时间。 它现在有效,因为它现在是未来。 如果您在接下来的 20 分钟内没有触摸表单然后单击提交,则应阻止提交,因为您选择的时间现在是过去 5 分钟。
  • 我考虑过直接在提交处理程序中添加验证。 这里有两个答案可以做到这一点。 但是,它对我来说并不理想,因为 Final Form 不会收到错误并将它们传递给表单字段的meta对象。 我的代码库很复杂并且严重依赖于meta对象来显示错误消息。 尝试在提交处理程序中复制该功能可能会起作用,但它很笨拙,并且违反了整个代码库中使用的约定。

图书馆作者在这里。 我总是对人们可以使我的假设无效的新方法着迷。 我的意思是以一种真诚积极的方式,因为它会导致学习。

🏁 Final Form 假设您的验证函数是“纯”或“幂等的” ,即当给定相同的值时将始终返回相同的结果。 这就是为什么在允许提交之前它不会再次运行同步验证(只是为了仔细检查):因为它已经存储了上次运行它的结果。 通过使用外部计时器,您已经使该假设无效。

如果您有更好/更简单/“更官方”的解决方案,我仍然很乐意看到它!

这个问题不需要修改器或装饰器。

更正式的方法是在onSubmit运行检查(您甚至可以重用this.validate )。 唯一棘手的部分是错误将作为meta.submitError ,因此您需要在显示错误时检查两者 像这样:

编辑提交时强制重新验证(React Final Form)

您已经在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 的形式使用此函数(我放入了 bot,因为我不确定组件结构):

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

并从 Form 组件中移除submitListener 装饰器:

decortaor={submitListener}

现在它将在提交之前检查验证,如果未验证则阻止它。

所以我找到了一种方法来做到这一点! 🎉 我使用了一个mutator并使用它的changeValue函数来“更改”相关字段的值(我提供相同的值)。 这反过来通知所有相关方表单状态的更改,并触发验证。 关键是在提交处理程序中调用 mutator,从而确保在提交表单时执行验证。 看看这个新的沙箱

相关位如下:

// 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被相应地使用!

如果您有更好/更简单/“更官方”的解决方案,我仍然很乐意看到它!

既然您想根据时间interval强制重新验证或停止提交表单,为什么不在提交按钮上使用disabled

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

我也阅读了react-final-form文档,但我认为它更容易,除非你有一个特定的案例需要使用meta来解决。

有另一个需要手动触发验证的用例:在这种情况下,我们有一个学生表格,如果我们有一个新学生,必须填写一个名为临时密码的字段,如果不是,该字段不是强制性的,为了简单起见,我们动态更新验证模式(我们有一个类似的案例,需要在完成某些提取操作时包含验证)。

我们应用了@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}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM