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

使用Yup验证带唯一key的Formik动态表单时校验失败如何解决?

问题原因

  1. 你传递给Formik的validationSchema是map方法返回的Yup校验对象数组,但Formik要求接收单个Yup.object()实例,这是校验不生效的核心原因。
  2. 没有动态生成对应字段的initialValues,空初始值会导致Formik无法识别动态生成的字段。
  3. 输入框未绑定Formik提供的handleChange等方法,校验状态无法同步到表单控件。

修正后的代码

import { useState, useMemo } from 'react';
import { nanoid } from 'nanoid';
import { Formik } from 'formik';
import * as Yup from 'yup';

const AddContact = () => {
  const [formData, setFormData] = useState([{key: nanoid()}])

  const createForm = () => {
    setFormData(prevFormData => [...prevFormData, {key: nanoid()}])
  }

  const deleteForm = (key) => {
    setFormData(prevFormData => prevFormData.filter(item => item.key !== key))
  }

  // 动态生成初始值
  const initialValues = useMemo(() => {
    const values = {};
    formData.forEach(data => {
      values[`name_${data.key}`] = '';
      values[`company_${data.key}`] = '';
      values[`mobile_no_${data.key}`] = '';
      values[`email_${data.key}`] = '';
    })
    return values;
  }, [formData]);

  // 动态生成单个校验 schema
  const validationSchema = useMemo(() => {
    const schemaFields = {};
    formData.forEach(data => {
      schemaFields[`name_${data.key}`] = Yup.string().required("Please enter a valid name");
      schemaFields[`company_${data.key}`] = Yup.string().required("Please enter a Company name");
      schemaFields[`mobile_no_${data.key}`] = Yup.number().typeError("Please enter a valid mobile number");
      schemaFields[`email_${data.key}`] = Yup.string().email().required("Please enter a valid email");
    })
    return Yup.object().shape(schemaFields);
  }, [formData]);

  return(
    <Formik
      initialValues={initialValues}
      validationSchema={validationSchema}
      // onSubmit={onSubmit}
    >
    {({ handleSubmit, values, handleChange, errors }) => {
      return(
        <div>
          {formData.map((data, index) => {
            return (
              <div key={data.key}>
                <button onClick={() => deleteForm(data.key)}>删除表单</button>
                <input 
                  name={`name_${data.key}`}
                  value={values[`name_${data.key}`]}
                  onChange={handleChange}
                />
                {errors[`name_${data.key}`] && <span style={{color: 'red'}}>{errors[`name_${data.key}`]}</span>}
                <input 
                  name={`company_${data.key}`}
                  value={values[`company_${data.key}`]}
                  onChange={handleChange}
                />
                {errors[`company_${data.key}`] && <span style={{color: 'red'}}>{errors[`company_${data.key}`]}</span>}
                <input 
                  name={`mobile_no_${data.key}`}
                  value={values[`mobile_no_${data.key}`]}
                  onChange={handleChange}
                />
                {errors[`mobile_no_${data.key}`] && <span style={{color: 'red'}}>{errors[`mobile_no_${data.key}`]}</span>}
                <input 
                  name={`email_${data.key}`}
                  value={values[`email_${data.key}`]}
                  onChange={handleChange}
                />
                {errors[`email_${data.key}`] && <span style={{color: 'red'}}>{errors[`email_${data.key}`]}</span>}
              </div>
            )
          })}
          <button onClick={createForm}>新增表单</button>
        </div>
      )
    }}
    </Formik>
  )
}

补充说明

  • 用useMemo包裹initialValues和validationSchema,避免formData变化之外的场景频繁重生成,减少不必要的性能消耗。
  • 代码里补充了错误提示的展示逻辑,你可以根据自己的UI需求调整样式。
  • 原代码存在标签未闭合、括号多余的语法问题,修正后可直接运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 06:21:01