React Hook Form:如何重置嵌套数组/对象脏状态且不影响其他字段
React Hook Form多步骤表单:重置特定嵌套字段脏状态问题
表单结构与需求
- 表单为多步骤结构
- 步骤3:选择演示相关主题
- 步骤4:根据选中主题动态加载问题
- 每个问题结构:
text字段(原始类型)options数组,每个选项包含:videos数组text字段
- 每个问题有独立保存按钮,保存后需仅重置该问题的所有字段脏状态,不影响表单其他部分。
示例表单数据
[ { "options": [ { "videos": [true], "text": true }, { "videos": [true], "text": true } ], "text": true }, { "options": [ { "videos": [true], "text": true }, { "videos": [true], "text": true } ], "text": true } ]
问题现状
通过resetField()编写递归函数重置已保存问题的脏字段:
- ✅ 对原始类型字段有效
- ❌ 无法重置数组和对象的脏状态
已尝试的递归函数
const clearNestedDirtyFields = (dirtyObj, basePath = '') => { Object.keys(dirtyObj).forEach(key => { const path = basePath ? `${basePath}.${key}` : key; if (Array.isArray(dirtyObj[key])) { dirtyObj[key].forEach((item, index) => { const itemPath = `${path}[${index}]`; if (item === true) { resetField(itemPath, { keepDirty: false, defaultValue: watch(itemPath) }); } else if (typeof item === 'object' && item !== null) { clearNestedDirtyFields(item, itemPath); } }); } else if (dirtyObj[key] === true) { resetField(path, { keepDirty: false, defaultValue: watch(path) }); } else if (typeof dirtyObj[key] === 'object' && dirtyObj[key] !== null) { clearNestedDirtyFields(dirtyObj[key], path); } }); };
已执行的排查操作
- 添加日志验证函数能正确遍历嵌套字段 ✅
- 显式调用
resetField(path, { keepDirty: false })✅ - 重置前调用
setValue(path, watch(path))✅ - 确认
resetField()对数组/对象脏状态无效 ❌
预期行为
保存单个问题时,仅清除该问题下所有字段(包括嵌套的options、videos)的脏状态,不影响其他问题或表单其他字段。
疑问
- 如何通过
resetField()重置嵌套数组/对象的脏状态,且不影响其他字段? - React Hook Form是否有更合适的替代实现方案?
脏值提取工具函数
export function getDirtyValues(dirtyFields, values) { return Object.keys(dirtyFields).reduce((prev, key) => { if (!dirtyFields[key] || values[key] === undefined) return prev; return { ...prev, [key]: typeof dirtyFields[key] === 'object' ? getDirtyValues(dirtyFields[key], values[key]) : values[key], }; }, {}); }
内容的提问来源于stack exchange,提问作者Zain
相关产品推荐
相关产品推荐

