React中如何实现Yup验证条件触发?解决字段联动验证问题
问题解决方案
一、仅在email字段输入时执行对应异步验证
默认情况下,Formik会在任意字段修改时验证整个Schema,这就是修改name时也触发email异步验证的原因。以下两种方式可解决该问题:
方法1:手动触发单个字段验证
利用Formik的validateField方法,在字段修改时仅验证当前字段:
import { useFormikContext } from 'formik'; // 在Formik内部组件中 const { validateField, handleChange, values } = useFormikContext(); const handleNameChange = (e) => { handleChange(e); validateField('name'); // 仅验证name字段 }; const handleEmailChange = (e) => { handleChange(e); validateField('email'); // 仅验证email字段 }; // 对应input绑定 <input name="name" onChange={handleNameChange} value={values.name} /> <input name="email" onChange={handleEmailChange} value={values.email} />
方法2:自定义validate函数,按需验证字段
放弃使用validationSchema,改用validate函数,根据touched状态仅验证已修改的字段:
import * as yup from 'yup'; const nameSchema = yup.object({ name: yup.string().required('Name is required') }); const emailSchema = yup.object({ email: yup.string().test('is-jimmy', '${path} is not Jimmy', function (value) { return new Promise((res) => { console.log('firing async validation'); setTimeout(() => res(value !== "foo@bar.com"), 1000); }); }) }); const validate = async (values, { touched }) => { const errors = {}; if (touched.name) { try { await nameSchema.validate({ name: values.name }, { abortEarly: false }); } catch (err) { errors.name = err.errors[0]; } } if (touched.email) { try { await emailSchema.validate({ email: values.email }, { abortEarly: false }); } catch (err) { errors.email = err.errors[0]; } } return errors; }; // 在Formik中使用 <Formik initialValues={{ name: '', email: '' }} validate={validate} onSubmit={(values) => console.log(values)} > {/* 表单内容 */} </Formik>
二、Formik是否支持传入多个验证Schema?
Formik不支持直接传入数组形式的validationSchema,但可以通过Yup的concat方法合并多个Schema,实现类似效果:
import * as yup from 'yup'; const userValidationSchema = yup.object({ name: yup.string().required() }); const emailSchema = yup.object({ email: yup.string().test('is-jimmy', '${path} is not Jimmy', function (value) { return new Promise((res) => { console.log('firing async validation'); setTimeout(() => res(value !== "foo@bar.com"), 1000); }); }) }); // 合并两个Schema const combinedSchema = userValidationSchema.concat(emailSchema); // 在Formik中使用合并后的Schema <Formik initialValues={{ name: '', email: '' }} validationSchema={combinedSchema} onSubmit={(values) => console.log(values)} > {/* 表单内容 */} </Formik>
合并后的Schema会同时应用两个原始Schema的验证规则,达到多Schema组合的效果。
内容的提问来源于stack exchange,提问作者Dante1021
相关产品推荐
相关产品推荐

