React Hook Form映射数组字段如何实现单字段独立校验
问题背景
需要基于对象数组批量生成表单字段,基于React Hook Form的Controller组件实现校验逻辑,渲染Material UI的TextField组件。
目前已实现带唯一值的字段渲染、空值阻止提交的基础逻辑,但存在校验错误全局触发的问题:只要任意一个条目字段为空,所有条目下的字段都会显示错误状态,期望错误仅在具体出错的单个字段上展示。
现有实现代码:
interface IItem { name: string quantity: number price: number total: number } interface IFormInput { name: string email: string items: IItem[] } const { control, handleSubmit, formState: { errors } } = useForm<IFormInput>() const handleFormSubmit: SubmitHandler<IFormInput> = (data) => { console.log(data) } const data = { name: 'john doe', email: 'johndoe@mail.com', items: [ { name: 'Banner Design', quantity: 1, price: 150, total: 150 }, { name: 'Email Design', quantity: 2, price: 200, total: 400 }, ], }
return ( <form onSubmit={handleSubmit(handleFormSubmit)}> {/* 姓名、邮箱字段Controller */} {data.items.map((item, index) => ( <Controller name={`items.${index}.name`} control={control} defaultValue={item.name} rules={{ required: "can't be empty", }} render={({ field }) => ( /* 无法正确访问 errors.items.${index}.name 对应错误 */ <FormControl error={!!errors.items}> <InputLabel>Item Name</InputLabel> <TextField {...field} /> </FormControl> )} /> {/* quantity、price、total字段Controller */} ))} <Button type='submit'>Submit</Button> </form> )
问题原因
错误判断逻辑使用!!errors.items,只要items数组下存在任意校验错误,该表达式就会返回true,导致所有行的表单项都被标记为错误状态,没有精确匹配当前索引下的具体字段错误。
修复方案
- 错误状态判断需要精确到对应索引的对应字段,通过可选链逐层安全访问嵌套错误对象即可,TypeScript环境下也不会报类型错误。
- 可以同时把错误提示文本绑定到TextField的
helperText属性,直接展示对应字段的校验提示。
修复后的字段渲染代码:
{data.items.map((item, index) => ( <Controller name={`items.${index}.name`} control={control} defaultValue={item.name} rules={{ required: "can't be empty", }} render={({ field }) => { // 精确匹配当前字段的错误对象 const fieldError = errors.items?.[index]?.name; return ( <FormControl error={!!fieldError}> <InputLabel>Item Name</InputLabel> <TextField {...field} error={!!fieldError} helperText={fieldError?.message} /> </FormControl> ) }} /> {/* quantity、price、total字段逻辑完全一致,仅需修改错误访问路径的末尾字段名即可 例:quantity字段错误取 errors.items?.[index]?.quantity */} ))}
如果觉得逐层写可选链比较繁琐,也可以直接导入React Hook Form提供的get工具方法,通过路径字符串直接取对应字段的错误,效果和可选链访问完全一致:
import { get } from 'react-hook-form'; // 在render函数中使用 const fieldError = get(errors, `items.${index}.name`);
内容的提问来源于stack exchange,提问作者Glen Ottley
相关产品推荐
相关产品推荐

