如何在React Final Form

时间:2019-07-11 11:19:42

标签: javascript reactjs react-final-form final-form

一旦表单的字段已经过验证,提交不会触发重新运行验证。提交表单后,有什么方法可以触发重新运行验证吗?

我有一个表单字段,如果未在特定时间范围内提交,其值可能变为无效。这不是异步的;我只是想介绍一种情况,在这种情况下,用户一段时间不会单击“提交”,而当他们最终单击时,该值将变为无效。最终形式会记住更改值后立即发生的验证结果,这意味着无论验证和提交之间经过了多长时间,不变的值仍然有效。这是我想要了解并改变的行为;在我的用例中,中间的时间很重要。我尝试使用beforeSubmit包中的final-form-submit-listener侦听器,但它仅提供对FormApi对象的访问。我尝试使用pauseValidation中的resumeValidationFormApi函数,但是它们无法实现我想要的功能,或者可能是我没有正确使用它们。我感觉如何执行此操作非常痛苦,但我无法弄清楚。 ?

我创建了this Sandbox来说明我的意思。

谢谢!

更新:一些其他信息:

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

5 个答案:

答案 0 :(得分:2)

您已经在onSubmit中放置了一个函数,为什么不只是添加所需的功能呢? event.preventDefault(),然后使用您的validate函数,它是组件的一部分,您可以访问。

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}>

然后从表单组件中删除 SubmitListener装饰器:

decortaor={submitListener}

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

答案 1 :(得分:2)

此处的图书馆作者。人们总是会对我的假设无效的新方式而着迷。我的意思是真诚的积极态度,因为它可以促进学习。

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

  

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

此问题无需更改器或修饰器。

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

Edit Force revalidation on submit (React Final Form)

答案 2 :(得分:1)

既然您要基于interval强制执行表单的重新验证或停止提交,为什么不对提交按钮使用disabled

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

我也阅读过react-final-form的文档,但我认为除非您有使用meta处理的特殊情况,否则它会更容易。

答案 3 :(得分:1)

还有另一个需要手动触发验证的用例:在这种情况下,我们获得了一个学生表格,如果我们有一个新学生,则必须填写一个名为 temporary password 的字段,否则字段不是必填字段,为简单起见,我们会即时更新验证模式(我们有类似的情况,每当完成某些提取操作时,都需要包含验证)。

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

答案 4 :(得分:0)

所以我找到了一种方法! ? 我使用mutator并使用它的sed -i -e 's#$AUTHENTICATION_ENDPOINT#'"$AUTHENTICATION_ENDPOINT"'#g' usr/share/nginx/html/config.json sed -i -e 's#$AUTHENTICATION_CLIENT_ID#'"$AUTHENTICATION_CLIENT_ID"'#g' /usr/share/nginx/html/config.json nginx -g 'daemon off;' 函数来“更改”相关字段的值(我提供相同的值)。反过来,这会将表单状态的更改通知所有相关方,并触发验证。关键是在提交处理程序内部调用mutator,从而确保在提交表单时执行验证。看看this new Sandbox

相关位如下:

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> ); }} /> ... ... 得到相应的使用!

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