如何使用 yup 异步验证与 formik 和 React 并避免看到第一个必需的验证

问题描述 投票:0回答:1

我有带有 formik 的 React 应用程序,是的,用于构建表单。

我需要创建包含输入列表和代码的表单,并且必须有 API 的异步验证,这将确认代码是否存在。

我尝试了以下表格:

import { Formik, Field, FieldArray, Form, ErrorMessage } from "formik";
import * as Yup from "yup";

interface BarcodeFormValues {
  barcodes: { code: string }[];
}

const validationSchema = Yup.object({
  barcodes: Yup.array().of(
    Yup.object().shape({
      code: Yup.string()
        .required("Barcode is required")
        .test("checkBarcodeExists", "Barcode does not exist", async (value) => {
          if (!value) return false;

          // add delay
          await new Promise((resolve) => setTimeout(resolve, 2000));

          // fake it, that validations failed
          return false;
        }),
    })
  ),
});

const initialValues: BarcodeFormValues = {
  barcodes: [{ code: "" }],
};

const BarcodeForm = () => {
  return (
    <Formik
      initialValues={initialValues}
      validationSchema={validationSchema}
      validateOnChange={true}
      validateOnBlur={false}
      onSubmit={(values) => {
        console.log("Submitted values:", values);
      }}
    >
      {({ values }) => (
        <Form>
          <FieldArray name="barcodes">
            {({ remove, push }) => (
              <div>
                {values.barcodes.length > 0 &&
                  values.barcodes.map((barcode, index) => (
                    <div key={index}>
                      <Field
                        name={`barcodes.${index}.code`}
                        placeholder="Enter barcode"
                      />
                      <ErrorMessage
                        name={`barcodes.${index}.code`}
                        component="div"
                      />
                      <button type="button" onClick={() => remove(index)}>
                        Delete
                      </button>
                    </div>
                  ))}
                <button type="button" onClick={() => push({ code: "" })}>
                  Add New
                </button>
              </div>
            )}
          </FieldArray>
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  );
};

export default BarcodeForm;

问题是,如果您添加更多输入并尝试在输入中键入某些内容,您可以看到第一条错误消息 - “需要条形码” - 但您在那里放置了一些内容,所以我不想看到此消息,然后一段时间后,您将看到异步验证的结果。

如何调整我的代码以摆脱首先看到此“必需的错误消息”并在输入确实为空的情况下仅显示此消息。

这是codesandbox中的示例:https://codesandbox.io/p/sandbox/x6fxzr

reactjs formik yup
1个回答
0
投票

为了成功实现这一目标,我们必须定制我们的错误。因此,删除

.required
并使用
ctx
自行解决错误。

const validationSchema = Yup.object({
  barcodes: Yup.array().of(
    Yup.object().shape({
      code: Yup.string()
        //.required("Barcode is required") Remove
        .test(
        "checkBarcodeExists",
        "Barcode does not exist",
        async (value, ctx) => {
          if (!value) // Solution!!
            return ctx.createError({ message: "Barcode is required" });

          // add delay
          await new Promise((resolve) => setTimeout(resolve, 2000));

          // fake it, that validations failed
          return false;
        }
      ),
    })
  ),
});
© www.soinside.com 2019 - 2024. All rights reserved.