为什么我的Lodash cloneDeepWith方法仅执行一次?
解决Lodash cloneDeepWith修改嵌套对象所有id的问题
你代码里的问题主要有两个:
- 逻辑范围错误:你把
handleChangeIds作为cloneDeepWith的自定义函数,但这个函数只在当前节点等于sections时才处理,大部分节点都被直接跳过了。 - 递归中断:在自定义函数里返回修改后的对象后,Lodash会停止递归处理这个对象的子属性,所以只有第一个匹配的id被修改,嵌套的id没被处理。
下面给你两种可行的解决方案:
方案一:先深拷贝,再递归遍历修改所有id
这种方法逻辑简单直观,完全避免cloneDeepWith的递归陷阱,也不会修改原数据:
// 假设你的id生成函数是这个 const generateObjectId = () => { return Math.random().toString(36).slice(2, 10); }; const cloneAndUpdateAllIds = (targetObj) => { // 先深拷贝整个对象,和原数据彻底隔离 const cloned = cloneDeep(targetObj); // 递归遍历所有节点修改id const updateIds = (item) => { if (!item || typeof item !== 'object') return; // 检查当前节点是否有id属性,有就修改 if (Object.hasOwn(item, 'id')) { item.id = generateObjectId(); } // 递归处理所有子节点 Object.values(item).forEach(updateIds); }; updateIds(cloned); return cloned; }; const DuplicateSection = () => { console.log('Original Store', form); const store = cloneAndUpdateAllIds(form); console.log('Modified', store); };
方案二:正确使用cloneDeepWith(不推荐,容易踩坑)
如果一定要用cloneDeepWith,需要确保修改id后仍让Lodash继续递归子属性。核心是手动处理递归,避免中断:
const DuplicateSection = () => { console.log('Original Store', form); const store = cloneDeepWith(form, (value) => { // 只处理有id属性的对象 if (value && Object.hasOwn(value, 'id')) { const cloned = { ...value }; cloned.id = generateObjectId(); // 手动递归处理子属性,避免Lodash中断递归 return cloneDeepWith(cloned, arguments.callee); } }); console.log('Modified', store); };
显然方案一更简洁可靠,推荐使用第一种方法。
内容的提问来源于stack exchange,提问作者PPs
相关产品推荐
相关产品推荐

