提问人:alexandr2006 提问时间:11/6/2023 更新时间:11/7/2023 访问量:69
如何根据输入内容验证 React Formik 表单?
how to validate react formik form depending on the input content?
问:
我需要按如下方式验证表单:表单中的所有字段都是可选的,但如果至少有一个字段输入了值,则它们都成为必填字段。
我写道:
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
答:
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
评论