React Hook Form动态字段添加错误提示遇TypeScript语法问题
React Hook Form动态字段错误提示修复方案
问题
在TypeScript环境下使用React Hook Form的useFieldArray实现动态字段时,无法正常获取错误提示(非动态字段工作正常)。原代码中errors.userInput[index].type?.message会触发errors.userInput可能未定义的类型错误,导致错误信息无法渲染。
原问题代码
const form = useForm<FormData>({ defaultValues: { userInput: [ { type: "", category: "", subcategory: "", }, ], }, }); const { register, handleSubmit, control, formState } = form; const { errors } = formState; const { fields, append, remove } = useFieldArray({ name: "userInput", control, }); return ( <div> <form onSubmit={handleSubmit(onSubmit)} noValidate> <div> {fields.map((field, index) => { return ( <div key={field.id}> <label>Add income or an expense?</label> <select defaultValue="" {...register(`userInput.${index}.type` as const, { required: { value: true, message: "Field is required" }, })} > <option value="expense">Expense</option> <option value="income">Income</option> <option value="liability">Liability</option> </select> <p className="error">{errors.userInput[index].type?.message}</p> </div> ); })} </div> </form> </div> );
问题原因
React Hook Form的errors对象仅在字段校验失败时才会生成对应层级的属性。当userInput数组中没有校验失败的项时,errors.userInput会是undefined,直接访问errors.userInput[index]会触发类型错误和运行时错误。而非动态字段的errors.type?.message使用了可选链,仅在type存在时访问message,所以不会报错。
修复方案
对errors对象的每一层嵌套都添加可选链操作符(?.),确保某一层属性不存在时不会抛出错误:
将错误提示行修改为:
<p className="error">{errors.userInput?.[index]?.type?.message}</p>
修改后的完整代码片段
{fields.map((field, index) => { return ( <div key={field.id}> <label>Add income or an expense?</label> <select defaultValue="" {...register(`userInput.${index}.type` as const, { required: { value: true, message: "Field is required" }, })} > <option value="expense">Expense</option> <option value="income">Income</option> <option value="liability">Liability</option> </select> {/* 这里添加了多层可选链 */} <p className="error">{errors.userInput?.[index]?.type?.message}</p> </div> ); })}
补充说明
如果需要在没有错误时隐藏错误提示元素,可以结合条件渲染:
{errors.userInput?.[index]?.type?.message && ( <p className="error">{errors.userInput?.[index]?.type?.message}</p> )}
内容的提问来源于stack exchange,提问作者rasputinsgoat
相关产品推荐
相关产品推荐

