Formik子组件使用validateAsync验证输入失效问题排查
问题原因
- 验证函数写法错误:Formik 字段的异步验证函数需要接收当前字段的值,返回 Promise 通过
resolve/reject反馈验证结果。你当前仅返回 Yup 对象,未执行实际验证逻辑,也未针对单个字段处理。 - 组件嵌套逻辑混乱:
useField已获取当前字段的field(含值、事件等)和meta(含错误、触达状态等),再嵌套使用Field组件会导致上下文冲突,meta.error无法正确捕获验证信息。 - 验证规则覆盖不全:仅针对
name1定义了规则,name2无对应验证逻辑。
修复后的代码
CustomForm 组件(仅修正拼写错误)
import { Field, Form, Formik, yupToFormErrors } from "formik"; import React, { Component } from "react"; import CustomField from "./CustomField"; // 修正文件名大小写 import * as Yup from "yup"; class CustomForm extends Component { state = {}; render() { return ( <Formik initialValues={{ name1: "", name2: "" }} onSubmit={(values) => { console.log(values); }} > <Form> <CustomField name="name1" label="name1"></CustomField> {/* 修正lable拼写为label */} <CustomField name="name2" label="name2"></CustomField> <button type="submit">send</button> </Form> </Formik> ); } } export default CustomForm;
CustomField 组件(核心逻辑修改)
import React from "react"; import { useField } from "formik"; import * as Yup from "yup"; const CustomField = ({ label, ...props }) => { const [field, meta] = useField(props); // 异步验证:接收字段值,返回Promise const validateAsync = async (value) => { // 可根据props.name扩展不同字段的验证规则 const schema = Yup.string().required("此字段为必填项"); try { await schema.validate(value, { abortEarly: false }); } catch (err) { return err.message; } }; // 将验证函数绑定到字段属性 const fieldWithValidation = { ...field, validate: validateAsync }; return ( <div> <label htmlFor={props.id || props.name}>{label}</label> <input {...fieldWithValidation} {...props} /> {meta.touched && meta.error && ( <div className="error">{meta.error}</div> )} </div> ); }; export default CustomField;
扩展说明
如果需要给不同字段设置差异化验证规则,可以通过给 CustomField 传递 validationSchema 属性实现:
// 在CustomForm中调用时传入自定义规则 <CustomField name="name1" label="name1" validationSchema={Yup.string().min(3, "至少输入3个字符")} ></CustomField>
随后在 CustomField 组件中用传入的 validationSchema 替换默认的必填规则即可。
内容的提问来源于stack exchange,提问作者Fatemeh
相关产品推荐
相关产品推荐

