如何使用Zod对嵌套数组中的details数组执行增删改操作
解决React Hook Form中嵌套数组(budgets.details)的操作问题
要操作budgets数组内部的details嵌套数组,核心是针对每个budgets项的索引,动态生成useFieldArray的路径,因为useFieldArray需要明确指定要操作的数组在表单结构中的位置。
实现步骤与代码示例
- 保留外层
budgets数组的useFieldArray实例,用于操作顶层预算项:
const { fields: budgetFields, append: appendBudget, remove: removeBudget } = useFieldArray({ control, name: 'budgets' }); // 修正追加预算项的逻辑,满足Zod对details数组的min(1)要求 const handleAppendMainArray = () => { appendBudget({ name: 'Nova diretriz', percent: 10, details: [{ description: 'Detalhe inicial', value: 0 }] }); };
- 遍历
budgetFields时,为每个预算项创建对应的details数组的useFieldArray实例:
{budgetFields.map((budget, budgetIndex) => { // 动态指定嵌套数组路径:budgets.[索引].details const { fields: detailFields, append: appendDetail, remove: removeDetail } = useFieldArray({ control, name: `budgets.${budgetIndex}.details` }); return ( <div key={budget.id} style={{ margin: '1rem 0', padding: '1rem', border: '1px solid #eee' }}> {/* 预算项的基础输入 */} <input {...register(`budgets.${budgetIndex}.name`)} placeholder="Nome da diretriz" style={{ marginRight: '0.5rem' }} /> <input type="number" {...register(`budgets.${budgetIndex}.percent`)} placeholder="Porcentagem" style={{ marginRight: '0.5rem' }} /> {/* 追加details的按钮 */} <button type="button" onClick={() => appendDetail({ description: 'Novo detalhe', value: 0 })}> + Adicionar Detalhe </button> {/* 渲染details列表 */} <div style={{ margin: '0.5rem 0 0 1rem' }}> {detailFields.map((detail, detailIndex) => ( <div key={detail.id} style={{ margin: '0.5rem 0' }}> <input {...register(`budgets.${budgetIndex}.details.${detailIndex}.description`)} placeholder="Descrição do recurso" style={{ marginRight: '0.5rem' }} /> <input type="number" {...register(`budgets.${budgetIndex}.details.${detailIndex}.value`)} placeholder="Valor" style={{ marginRight: '0.5rem' }} /> <button type="button" onClick={() => removeDetail(detailIndex)}> Remover </button> </div> ))} </div> {/* 删除当前预算项 */} <button type="button" onClick={() => removeBudget(budgetIndex)} style={{ marginTop: '0.5rem' }}> Remover Diretriz </button> </div> ); })}
关键注意事项
- 路径格式:必须使用点语法
budgets.${budgetIndex}.details来指定嵌套数组的位置,确保useFieldArray能正确定位到目标数组。 - Zod约束兼容:追加预算项时,必须给
details数组传入至少一个初始元素,否则会触发Zod的min(1)校验错误。 - 子组件优化:如果表单结构复杂,建议将单个预算项抽成独立子组件,把
control和budgetIndex作为props传递,在子组件内部处理details数组的操作,让代码更清晰。
内容的提问来源于stack exchange,提问作者Aliton Oliveira
相关产品推荐
相关产品推荐

