如何实现Formik跳过与初始值相等字段的校验?
解决Formik不对与初始值相等的字段执行校验的问题
针对编辑表单场景(初始值为项目原有属性,新增校验规则不强制修改原有值),以下是两种可行方案:
方案一:Formik原生validate函数实现
放弃validationSchema,改用validate函数手动控制校验逻辑,仅当字段值与初始值不同时执行校验:
import React from "react"; import { Formik, Form, Field } from "formik"; import { TextField, Button } from "@mui/material"; const initialValues = { email: "existing-user@example.com" }; // 单独定义邮箱校验规则,方便复用 const validateEmail = (value) => { if (!value) return "Email is required"; if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return "Invalid email format"; return undefined; }; export default function App() { return ( <Formik initialValues={initialValues} validate={(values) => { const errors = {}; // 仅当邮箱值与初始值不一致时,执行校验 if (values.email !== initialValues.email) { const emailError = validateEmail(values.email); if (emailError) errors.email = emailError; } return errors; }} onSubmit={(values) => { alert(JSON.stringify(values, null, 2)); }} > {({ errors, touched }) => ( <Form> <Field as={TextField} name="email" label="Email" error={touched.email && Boolean(errors.email)} helperText={touched.email && errors.email} fullWidth margin="normal" /> <Button type="submit" variant="contained" color="primary"> Submit </Button> </Form> )} </Formik> ); }
该方案逻辑直观,后续新增字段时,只需在validate函数中添加对应字段的判断即可。
方案二:Yup条件校验实现
若希望保留Yup的Schema语法,可通过自定义校验规则,给字段添加"值不等于初始值时才校验"的条件:
import React from "react"; import { Formik, Form, Field } from "formik"; import { TextField, Button } from "@mui/material"; import * as Yup from "yup"; const initialValues = { email: "existing-user@example.com" }; // 传入初始值生成校验Schema const createValidationSchema = (initialVals) => { return Yup.object({ email: Yup.string() // 未修改初始值则直接通过校验 .test( "unmodified-field", "", (value) => value === initialVals.email ) // 修改后执行完整邮箱校验,并抛出对应错误 .transform(function (value) { if (value !== initialVals.email) { try { Yup.string() .email("Invalid email format") .required("Email is required") .validateSync(value); } catch (err) { this.createError({ message: err.message }); } } return value; }) }); }; export default function App() { const validationSchema = createValidationSchema(initialValues); return ( <Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={(values) => { alert(JSON.stringify(values, null, 2)); }} > {({ errors, touched }) => ( <Form> <Field as={TextField} name="email" label="Email" error={touched.email && Boolean(errors.email)} helperText={touched.email && errors.email} fullWidth margin="normal" /> <Button type="submit" variant="contained" color="primary"> Submit </Button> </Form> )} </Formik> ); }
此方案保留了Yup的声明式语法,适合习惯用Yup管理校验规则的场景。
扩展提示(针对后续需求)
若后续需要将未修改但不符合新规则的字段转为警告(黄色提示),可在validate函数或Yup规则中添加自定义warnings对象,在UI层判断并渲染警告样式,不阻止表单提交。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

