React Hook Form动态字段的Yup验证问题求助
React Hook Form 动态字段结合Yup验证解决方案
你的代码核心问题是Yup Schema未针对动态生成的childrenNames数组配置验证规则,同时存在几处React Hook Form的使用细节错误,以下是完整修正方案:
修正后的父组件代码
import { useFieldArray, useForm } from 'react-hook-form'; import * as yup from 'yup'; import { yupResolver } from '@hookform/resolvers/yup'; import { useCallback, useMemo } from 'react'; import { Row, Col } from '你的UI库路径'; // 替换为实际UI库路径 import Input from './Input'; // 替换为实际子组件路径 // 完善Yup验证规则,新增childrenNames数组验证 const schema = yup.object().shape({ name: yup.string().required('姓名不能为空'), surname: yup.string().required('姓氏不能为空'), // 验证数组中每个子项的childrenName字段必填 childrenNames: yup.array().of( yup.object().shape({ childrenName: yup.string().required('孩子姓名不能为空') }) ) }); const PersonalInformation = () => { // 解构出control,useFieldArray必须依赖它 const { handleSubmit, register, control, formState: { errors } } = useForm({ resolver: yupResolver(schema), defaultValues: { name: '', // 补充name和surname的默认值 surname: '', childrenNames: [{ childrenName: '' }], }, }); // useCallback添加正确依赖,避免闭包问题 const handleAppend = useCallback(() => append({ childrenName: '' }), [append]); const removeFields = useCallback((index) => remove(index), [remove]); const { append, remove, fields } = useFieldArray({ control, name: 'childrenNames', }); // useMemo补充register到依赖,符合Hook规则 const nameInput = useMemo( () => <Input id="name" inputName="你的姓名" register={register} name="name" error={errors?.name?.message} required />, [errors?.name, register], ); const surNameInput = useMemo( () => <Input id="surname" inputName="你的姓氏" register={register} name="surname" error={errors?.surname?.message} required />, [errors?.surname, register], // 修复原代码缺少的逗号 ); // 表单提交逻辑 const onSubmit = (data) => { console.log('表单数据:', data); // 此处添加你的提交逻辑 }; return ( <form onSubmit={handleSubmit(onSubmit)}> <Row> <Col xs={4}>{nameInput}</Col> <Col xs={4}>{surNameInput}</Col> </Row> {fields?.map((field, index) => ( <Row key={field?.id} className="mt-5"> <Col xs={4}> <Input inputName="孩子姓名" name={`childrenNames[${index}].childrenName`} register={register} error={errors?.childrenNames?.[index]?.childrenName?.message} id={`childrenName-${index}`} // 给动态字段设置唯一id required /> </Col> <div className="final-buttons"> <div className="btn-start"> <button onClick={handleAppend} type="button"> + 添加 </button> </div> {/* 至少保留一个孩子字段,可根据需求调整 */} {fields.length > 1 ? ( <div> <button type="button" onClick={() => removeFields(index)}>删除</button> </div> ) : null} </div> </Row> ))} {/* 补充提交按钮 */} <button type="submit" className="mt-3">提交</button> </form> ); }; export default PersonalInformation;
修正后的子组件代码
const Input = ({ error, inputName, id, register, type = 'text', name, placeholder, required }) => { return ( <div className="form-input"> <label htmlFor={id}> {inputName} {required && <span className="text-red-500 ml-1">*</span>} </label> {/* 修复原代码的inputType错误,改为props传入的type */} <input type={type} {...register(name)} id={id} placeholder={placeholder} className={`${error ? 'error-status' : ''}`} /> {/* 显示错误提示 */} {error && <p className="text-red-500 text-sm mt-1">{error}</p>} </div> ); }; export default Input;
关键改动说明
- Yup规则完善:新增
childrenNames数组验证,确保每个动态添加的孩子姓名字段非空。 - Hook依赖修正:
useCallback添加append/remove依赖,useMemo补充register依赖,避免闭包导致的状态异常。 - 错误信息传递:给动态字段的Input组件传递对应索引的错误信息,让错误提示正常渲染。
- 细节修复:补充表单默认值、修复子组件
inputType参数错误、添加提交按钮、给动态字段设置唯一id等。
内容的提问来源于stack exchange,提问作者Rahil Əliyev
相关产品推荐
相关产品推荐

