12

我有一个withFormik()用于我的 React 应用程序中使用的表单的验证模式,这validateJql()是我的自定义验证函数yup

validationSchema: Yup.object().shape({
            rework: Yup.string().required("Rework query is required").validateJql(), 
            originalEstimate: Yup.string().required("Original Estimate query is required").validateJql()
        })

我的表单组件是这样的:

const addSomeForm = (props) => {
    const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleSubmit,
    } = props;

return (
        <form onSubmit={handleSubmit}>
             <div className="form-group">
                  <div>
                      <label htmlFor="name" className="col-form-label"><b>Rework Query:</b></label>
                      <textarea id="query.rework" rows="5" type="text" className="form-control" placeholder="Enter JQL with aggregate Function" value={values.query.rework} onChange={handleChange} required />
                       {errors.query && errors.query.rework && touched.query && <span className="alert label"> <strong>{errors.query.rework}</strong></span>}
                   </div>
             </div>
             <div className="form-group">
                 <div>
                      <label htmlFor="name" className="col-form-label"><b>Original Estimate:</b></label>
                       <textarea id="query.originalEstimate" rows="5" type="text" className="form-control" placeholder="Enter JQL with aggregate Function" value={values.query.originalEstimate} onChange={handleChange} required />
                       {errors.query && errors.query.originalEstimate && touched.query && <span className="alert label"> <strong>{errors.query.originalEstimate}</strong></span>}
                 </div>
             </div>
       </form>
    )

现在,我想要做的不是在表单提交时运行验证,如果该字段没有被触摸rework并且originalEstimate也不是空的。如何使用withFormikHOC 或Yup? 我已经部分浏览了Yup文档和Formik文档,但找不到适合我的问题的东西。

在提交一次表单并在此之后进行编辑以对其中一些字段进行细微调整后就是这种情况。如果有多个字段并且只编辑了一些字段,我不想对所有存在的字段进行验证。

先感谢您。

4

2 回答 2

1

这是formik 文档中所述的默认期望行为,但我认为您可以执行以下操作:

而不是使用validationSchema,使用validate功能。

Validate 函数的工作方式与您的 validationSchema 工作方式相同。您只需要从带有混合.validate 的函数中以编程方式使用Yup

因此,您可以完全控制表单中的所有道具。您还可以使用getFieldMeta来获取该字段的touched 和value 并在您的验证中使用它。或者从touched对象中获取这些道具getIn

就像是:


// Some util functions
function mapYupErrorsToFormikErrors(err: { inner: any[] }) {
  return err.inner
    .filter((i: { path: any }) => !!i.path)
    .reduce(
      (curr: any, next: { path: any; errors: any[] }) => ({
        ...curr,
        [next.path]: next.errors[0],
      }),
      {},
    )
}

function validateSchema(values: object, schema: Schema<object>) {
  return schema
    .validate(values, {
      abortEarly: false,
      strict: false,
    })
    .then(() => {
      return {}
    })
    .catch(mapYupErrorsToFormikErrors)
}


// Your validation function, as you are using `withFormik` you will have the props present

function validateFoo(values, props) {
  const { touched, value } = props.getFieldMeta('fooFieldName') // (or props.form.getFieldmeta, not sure)

  const errors = validateSchema(values, yourYupSchema)

  if (!touched && !value && errors.fooFieldName) {
    delete errors.fooFieldName
  } 

  return errors  
}

好吧,touched 可能不适用于您的用例,因为 formik 可能会在提交时将其设置为 true,但是您拥有所有道具,并且您可以使用不同的东西,例如空值或您手动设置的其他状态道具。你在那里得到了所有的控制。

于 2020-06-02T00:45:56.900 回答
1

我有一个类似的问题,我最终创建了另一个字段,我在显示编辑屏幕时设置了值。然后我在这样的测试函数中进行比较:

originalField: yup.string().default(''),

field: yup.string().default('').required('Field is required.').test('is-test',
    'This is my test.',
    async (value, $field) => {
      if($field.parent.originalField !== '' && value === $field.parent.originalField) return true
      return await complexAsyncValidation(value)
    }

不完美,但绝对有效

于 2021-03-11T17:02:13.347 回答