如何基于键数组访问和修改嵌套对象?(React+MUI场景)
解决方案
1. 实现嵌套值的访问与更新工具函数
核心是通过两个工具函数,处理路径数组访问嵌套值和不可变更新嵌套值的逻辑:
访问嵌套值
// 根据keyList安全获取嵌套对象的值,路径不存在时返回undefined const getNestedValue = (obj, keyList) => { return keyList.reduce((current, key) => { return current?.[key] ?? undefined; }, obj); };
不可变更新嵌套值
// 根据keyList不可变更新嵌套对象的值,自动创建不存在的中间层级 const setNestedValue = (obj, keyList, newValue) => { const newObj = {...obj}; let currentLayer = newObj; // 遍历到倒数第二个键,每一层都浅拷贝保证不可变性 for (let i = 0; i < keyList.length - 1; i++) { const key = keyList[i]; // 若当前层级无此键或不是对象,创建空对象 currentLayer[key] = {...(currentLayer[key] ?? {})}; currentLayer = currentLayer[key]; } // 设置最后一个键的新值 const lastKey = keyList[keyList.length - 1]; currentLayer[lastKey] = newValue; return newObj; };
2. 递归表单组件实现
结合MUI的TextField,封装递归表单字段组件,传入路径数组、表单状态和更新函数即可:
import { TextField } from '@mui/material'; const RecursiveFormField = ({ form, setForm, keyList, label }) => { const currentValue = getNestedValue(form, keyList); const handleChange = (e) => { const updatedForm = setNestedValue(form, keyList, e.target.value); setForm(updatedForm); }; return ( <TextField label={label} value={currentValue ?? ''} onChange={handleChange} margin="normal" /> ); }; // 示例调用:对应form.user.profile.name路径 // <RecursiveFormField form={form} setForm={setForm} keyList={['user', 'profile', 'name']} label="用户名" />
3. 动态遍历嵌套对象生成表单
如果表单结构是动态嵌套的,可通过递归遍历自动生成完整表单:
const RecursiveForm = ({ form, setForm, parentKeyList = [] }) => { return Object.entries(form).map(([key, value]) => { const currentKeyList = [...parentKeyList, key]; // 当前值为对象时,递归生成子表单区域 if (typeof value === 'object' && value !== null && !Array.isArray(value)) { return ( <div key={key} style={{ marginLeft: 20 }}> <h4>{key}</h4> <RecursiveForm form={value} setForm={setForm} parentKeyList={currentKeyList} /> </div> ); } // 非对象值直接渲染输入框 else { return ( <RecursiveFormField key={key} form={form} setForm={setForm} keyList={currentKeyList} label={key} /> ); } }); }; // 根组件使用示例 const App = () => { const [form, setForm] = useState({ user: { profile: { name: '', age: '' }, contact: { email: '', phone: '' } } }); return ( <div style={{ padding: 20 }}> <h3>嵌套递归表单</h3> <RecursiveForm form={form} setForm={setForm} /> </div> ); };
关键说明
- 不可变更新:每一层对象都做浅拷贝,确保React能检测到状态变化,符合React状态更新规则。
- 路径安全:处理了路径不存在的边界情况,避免出现
Cannot set property of undefined错误。 - 递归路径跟踪:通过
parentKeyList拼接当前键,实现递归过程中对嵌套路径的完整追踪。
内容的提问来源于stack exchange,提问作者psygo
相关产品推荐
相关产品推荐

