Formik 的 "isValid" 报告为 true,即使验证模式报告了一个错误。

3

看起来在某些情况下,Formik的“isValid”标志被设置为true,即使表单值不应被视为有效。我有一个工作的codesandbox示例,下面展示了这个问题。

https://m229l.csb.app/

我用于表单的验证模式如下:

const validationSchema = Yup.object().shape(
  {
    heading: Yup.string().required('Heading required.'),
    image: Yup.string().when('placeholder', {
      is: '',
      then: Yup.string().required(
        'Please either choose an image, or a placeholder.'
      ),
      otherwise: Yup.string(),
    }),
    placeholder: Yup.string().when('image', {
      is: '',
      then: Yup.string().required(
        'Please either choose an image, or a placeholder.'
      ),
      otherwise: Yup.string(),
    }),
  },
  [['image', 'placeholder']]
);

在输出 Formik 的 isValid 标志时,以下值为 true

{ heading: 'a', image: '', placeholder: '' }

架构规定“image”或“placeholder”字段之一必须存在,但在上述情况下它们不存在。然而,isValid标志为true

使用Yup手动测试时,我得到了预期的结果:

validationSchema.validate(values).then(...).catch(...);

在codesandbox中可以进一步看到这一点。我错过了什么吗?当Formik验证值时,背后还有更多的事情发生吗?

3个回答

4

我也遇到了相同的问题,因此除了使用formik.isValid之外,我还使用了另一个属性formik.touched,只有当以下条件都满足时,我才会将表单视为有效formik.isValid = trueObject.keys(formik.touched).length > 0(至少要触摸一些字段),如下所示:

const isFormValid = formik.isValid && Object.keys(formik.touched).length > 0; // WITH lodash: formik.isValid && !_.isEmpty(formik.touched)
if (isFormValid) {
 // NOW SUBMIT THE FORM OR DO YOUR NEXT STEP
}

2
你需要在 Formik 中添加 validateOnMount,以便在验证初始值时进行验证:
<Formik 
  validateOnMount={true} 
  initialValues={initialValues}
  validationSchema={validationSchema} 
>
// your form
</Formik>

0

指定 validateOnMount=true 不会在使用 resetForm() 手动重置表单时触发验证。

在 Formik v2 中,您可以在 resetForm() 之后调用 validateForm() 来重新运行验证。

用法:

import { useRef } from "react";

const formRef = useRef();
const initialValues = { foo: "", bar: "" };
const appliedValues = { foo: "bar", bar: "foo" };

const someFunc = () => {
    formRef.current.resetForm({ values: { ...initialValues, ...appliedValues} });
    setTimeout(() => formRef.current.validateForm());
    // note1: resetForm() is not returning Promise, therefore we cannot use .then() chaining, and we need to use setTimeout to delay the validations until form is done resetting. Else, the validation will happen before reset is complete.
    // note2: validateForm() is a promise function, so you can use .then() to chain with other formik functions.
};

<Formik
    innerRef={formRef}
    validateOnMount // <-- use this so it works for initial render
    initialValues={initialValues}
    ...
>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接