React Hook Form结合Zod处理数组邮箱输入的同步与初始值问题
React Hook Form + Zod 邮箱数组输入框问题解决办法
问题场景
页面接收emails: string[]类型的初始邮箱数据,通过emailsFields.map((field, index) => {...})渲染对应数量的输入框,同时用Zod配置了如下校验规则:
export const emails = validationService .string({ required_error: '邮箱为必填项' }) .email('请输入有效的邮箱地址') .array()
遇到两个矛盾的问题:
- 把输入框的
name设为emails时,初始邮箱值能正常显示,但在任意输入框输入内容时,所有输入框的值会同步变化 - 改
name为name={[${field.id}].emails}后,输入框不再同步变化,但初始接收的邮箱值无法渲染到输入框里
解决步骤及代码示例
核心问题原因
[${field.id}].emails的写法会把表单字段结构改成嵌套格式,和你传入的string[]初始数据、Zod数组校验规则不匹配,导致初始值无法绑定;而直接用emails作为name会让所有输入框绑定到同一个数组字段,所以会同步变化。
正确实现方式
配置useFieldArray的正确字段名
用useFieldArray管理数组字段时,要指定对应数组的字段名(这里是emails),每个输入框的name要对应数组的索引位置,格式为emails.${index}或emails[${index}]。正确传入初始值
在调用useForm时,把接收的初始邮箱数组传入defaultValues的emails字段,确保useFieldArray能读取并初始化输入框。保持Zod校验规则匹配
你的Zod规则string().array()刚好对应emails数组字段,不需要修改。
完整代码示例
import { useForm, useFieldArray } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; // 替换成你的校验服务引入路径 import { validationService } from './path/to/validation-service'; // Zod校验规则 const emailSchema = validationService .string({ required_error: '邮箱为必填项' }) .email('请输入有效的邮箱地址') .array(); const EmailInputList = ({ emails: initialEmails }) => { const { register, control, formState: { errors } } = useForm({ resolver: zodResolver(emailSchema), defaultValues: { // 传入初始邮箱数组,为空时设默认空数组 emails: initialEmails || [] } }); const { fields, append, remove } = useFieldArray({ control, // 对应表单中的数组字段名 name: 'emails' }); return ( <div> {fields.map((field, index) => ( <div key={field.id} style={{ marginBottom: '8px' }}> <input {...register(`emails.${index}`)} placeholder="请输入邮箱地址" type="email" /> {/* 显示对应索引的错误提示 */} {errors.emails?.[index] && ( <p style={{ color: 'red', margin: '4px 0 0 0' }}> {errors.emails[index].message} </p> )} <button type="button" onClick={() => remove(index)} style={{ marginLeft: '8px' }} > 删除 </button> </div> ))} <button type="button" onClick={() => append('')}> 添加邮箱 </button> </div> ); }; export default EmailInputList;
关键说明
- 输入框name用
emails.${index}是React Hook Form推荐的数组字段绑定方式,能正确关联到数组的对应索引项,不会出现同步变化的问题 - 必须在
defaultValues中设置emails字段的初始值,否则useFieldArray无法初始化渲染初始的邮箱内容 - 如果需要动态添加/删除输入框,直接用
useFieldArray提供的append和remove方法即可,内部会自动维护数组的状态和索引
内容的提问来源于stack exchange,提问作者Vagner Wentz
相关产品推荐
相关产品推荐

