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

React中Formik+Yup密码验证:一次性展示所有错误并逐步消除

实现Formik+Yup密码多规则验证并批量展示/移除错误提示

要实现一次性展示所有密码验证错误,且满足规则后逐步移除提示,需要两步核心操作:关闭Yup的提前终止验证,以及调整验证规则确保所有规则都被检查并收集错误,具体实现如下:

1. 配置Formik禁用提前终止验证

Yup默认开启abortEarly: true,意味着只要遇到第一个验证失败就停止后续检查,所以必须在Formik配置中显式设置abortEarly: false,确保所有验证规则都能执行并收集所有错误。

用Formik组件示例:

import { Formik, Form, Field } from 'formik';
import * as Yup from 'yup';

// 后续定义userSchema...

<Formik
  initialValues={{ password: '' }}
  validationSchema={userSchema}
  abortEarly={false} // 关键配置:不提前终止验证
  validateOnChange={true} // 实时验证,输入时更新错误状态
  validateOnBlur={true}
  onSubmit={(values) => {
    console.log('Submitted:', values);
  }}
>
  {({ errors, touched }) => (
    <Form>
      {/* 表单渲染内容 */}
    </Form>
  )}
</Formik>

用useFormik Hook示例:

import { useFormik } from 'formik';
import * as Yup from 'yup';

const formik = useFormik({
  initialValues: { password: '' },
  validationSchema: userSchema,
  abortEarly: false,
  validateOnChange: true,
  onSubmit: (values) => {
    console.log('Submitted:', values);
  },
});

2. 调整Yup验证规则,收集所有错误

默认的链式验证(如.min().matches())会在第一个失败时停止,无法收集所有不满足的规则错误。我们可以用test方法自定义验证逻辑,一次性检查所有规则并返回所有错误消息。

自定义验证函数+Yup test:

// 自定义密码验证逻辑,返回所有不满足的错误消息
const validatePasswordRules = (value) => {
  const errorMessages = [];
  // 规则1:至少12个字符
  if (!value || value.length < 12) {
    errorMessages.push('At least 12 characters long');
  }
  // 规则2:同时包含大小写字母
  if (!value || !(/[A-Z]/.test(value) && /[a-z]/.test(value))) {
    errorMessages.push('Mix of uppercase and lowercase letters');
  }
  // 规则3:至少包含一位数字
  if (!value || !/[0-9]/.test(value)) {
    errorMessages.push('At least one digit (0-9)');
  }
  // 规则4:至少包含一个特殊字符
  if (!value || !/[!%&@#$^*?_~.,]/.test(value)) {
    errorMessages.push('At least one special character (!%&@#$^*?_~.,)');
  }
  return errorMessages;
};

// 定义Yup Schema
const userSchema = Yup.object({
  password: Yup.string()
    .test(
      'password-all-rules',
      'Password validation failed',
      (value) => {
        const errors = validatePasswordRules(value);
        if (errors.length > 0) {
          // 抛出包含所有错误的ValidationError
          throw new Yup.ValidationError(errors, value, 'password');
        }
        return true;
      }
    )
});

3. 渲染所有错误提示

现在errors.password会是一个包含所有未满足规则的错误数组,我们可以遍历它来展示每一条错误,当用户输入满足某条规则时,该错误会自动从数组中移除:

<div className={styles.field_outer_wrapper}>
  <div className={styles.field_inner_wrapper}>
    <label htmlFor="password" className={styles.label}>
      Password*
    </label>
    <Field
      name="password"
      id="password"
      type="password"
      className={`${styles.text_field} ${touched.password && errors.password ? styles.alert : ''}`}
    />
    {/* 渲染所有错误提示 */}
    {touched.password && errors.password && (
      <div className={styles.error_container}>
        {errors.password.map((error, idx) => (
          <div key={idx} className={styles.error_item}>
            • {error}
          </div>
        ))}
      </div>
    )}
  </div>
</div>

关键说明

  • abortEarly: false是核心,确保Formik收集所有验证错误
  • 自定义test方法让所有规则都被检查,不会因某条规则失败而跳过其他
  • validateOnChange: true保证用户输入时实时验证,错误提示会随输入动态更新(满足规则的错误自动消失)

内容的提问来源于stack exchange,提问作者Jonas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:05:15