如何根据输入内容验证 React Formik 表单?

how to validate react formik form depending on the input content?

提问人:alexandr2006 提问时间:11/6/2023 更新时间:11/7/2023 访问量:69

问:

我需要按如下方式验证表单:表单中的所有字段都是可选的,但如果至少有一个字段输入了值,则它们都成为必填字段。

我写道:

const getRequiredSchema = () => {
   return Yup.string().when(["full_name", "email", "password"], {
     is: (...args) => args.some((item) => !!item),
     then: Yup.string().required("Required!")
   });
 };
...
validationSchema: Yup.object({
      full_name: getRequiredSchema(),
      email: getRequiredSchema(),
      password: getRequiredSchema()
})

并出现错误:循环依赖,节点为:“密码” 好的,我重写了代码,试图摆脱循环:

const getRequiredSchema = (field) => {
  return Yup.string().when(
    ["full_name", "email", "password"].filter((f) => f !== field),
    {
      is: (...args) => args.some((item) => !!item),
      then: Yup.string().required("Required!")
    }
  );
};
....
validationSchema: Yup.object({
      full_name: getRequiredSchema("full_name"),
      email: getRequiredSchema("email"),
      password: getRequiredSchema("password")
})

但错误并没有消失。如何正确编写验证? 这是 codesandbox 上的完整 cole

reactjs formik 是的

评论

0赞 Ahmet Firat Keler 11/10/2023
如果对您有用,请标记已接受的答案

答:

1赞 Akeel Ahmed Qureshi 11/6/2023 #1

你可以试试这个代码,如果你想坚持使用Yup,一种解决方法是通过创建一个自定义验证函数来删除循环依赖关系,该函数检查是否至少有一个字段具有值。

import React from "react";
import { useFormik } from "formik";
import * as Yup from "yup";

const validationSchema = (values) => {
  return Yup.object().shape({
    full_name: values.email || values.password ? Yup.string().required("Required") : Yup.string(),
    email: values.full_name || values.password ? Yup.string().required("Required") : Yup.string(),
    password: values.full_name || values.email ? Yup.string().required("Required") : Yup.string()
  });
};

export default function App() {
  const formik = useFormik({
    initialValues: {
      full_name: "",
      email: "",
      password: ""
    },
    validationSchema: () => validationSchema(formik.values),
    onSubmit: (values) => {
      alert(JSON.stringify(values, null, 2));
    }
  });

  return (
    <div className="App">
      <form onSubmit={formik.handleSubmit}>
        <div>
          <label>Full Name</label>
          <input
            type="text"
            name="full_name"
            maxLength="10"
            value={formik.values.full_name}
            onChange={formik.handleChange}
          />
          {formik.errors.full_name && formik.touched.full_name && (
            <p>{formik.errors.full_name}</p>
          )}
        </div>
        <div>
          <label>Email</label>
          <input
            type="email"
            name="email"
            value={formik.values.email}
            onChange={formik.handleChange}
          />
          {formik.errors.email && formik.touched.email && (
            <p>{formik.errors.email}</p>
          )}
        </div>
        <div>
          <label>Password</label>
          <input
            type="password"
            name="password"
            value={formik.values.password}
            onChange={formik.handleChange}
          />
          {formik.errors.password && formik.touched.password && (
            <p>{formik.errors.password}</p>
          )}
        </div>

        <div>
          <button type="submit">Submit</button>
        </div>
      </form>
    </div>
  );
}
1赞 Ahmet Firat Keler 11/6/2023 #2

试试 Yup Lazy

const validationSchema = Yup.lazy((values) => {
  const {full_name, email, password} = values
  if (full_name || email || password) {
    return Yup.object().shape({
      full_name: Yup.string().required(),
      email: Yup.string().required(),
      password: Yup.string().required(),
    })
  }
  return Yup.mixed().notRequired()
})

我已经修复了您的示例:https://codesandbox.io/s/react-formik-yup-forked-s6w7y3?file=/src/App.js