You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:25:28