Проблема в вашем коде заключается в том, что, пока вы вызываете updateChildren(children, index)
, вы ничего не делаете с результатом.
Этот код создает новый массив и не изменяет ваш старый объект в место. (Я искренне одобряю это!) Но это означает, что когда вы звоните детям updateChildren
, вам действительно нужно что-то сделать с результатом.
Вот твик к вашему коду, который это исправит.
const updateChildrenIds = (childrenData = [], index) => {
const newData = childrenData.map(value => {
const { id, children} = value; // no default value for children
// removed the recursive call from here
const splitIds = id.split('.');
splitIds[0] = index;
const newId = splitIds.join('.');
const newValue = {...value, id: newId}
if (children) { // moved here
newValue.children = updateChildrenIds(children, index)
}
return newValue;
});
return newData;
};
const testData = [{name: "Cat", id: "0"}, {name: "Dog", id: "1"}, {name: "Rabbit", id: "2", children: [{name: "Little Rabbit Child", id: "2.children[0]", children: [{name: "Little Rabbit Child One", id: "2.children[0].children[0]", children: [{name: "Rat", id: "2.children[0].children[0].children[0]"}]}, {name: "Little Rabbit Child Two", id: "2.children[0].children[1]"}, {name: "Little Rabbit Child Three", id: "2.children[0].children[2]"}]}, {name: "Little Rabbit Son", id: "2.children[1]"}, {name: "Little Rabbit Daughter", id: "2.children[2]"}]}, {name: "Elephant", id: "3", children: [{name: "Little Elephant", id: "3.children[0]"}]}]
console .log (updateChildrenIds (testData [2] .children, 1))
.as-console-wrapper {min-height: 100% !important; top: 0}
Но если бы я написал это, я бы сделал это по-другому. Итак, вот еще один подход, который более точно соответствует нормам функционального программирования:
const updateIds = (nodes, baseId) =>
nodes .map (({id, children, ...rest}) => ({
...rest,
id: id .replace (/^\d+/, baseId),
... (children && {children: updateIds (children, baseId)})
}))
const testData = [{name: "Cat", id: "0"}, {name: "Dog", id: "1"}, {name: "Rabbit", id: "2", children: [{name: "Little Rabbit Child", id: "2.children[0]", children: [{name: "Little Rabbit Child One", id: "2.children[0].children[0]", children: [{name: "Rat", id: "2.children[0].children[0].children[0]"}]}, {name: "Little Rabbit Child Two", id: "2.children[0].children[1]"}, {name: "Little Rabbit Child Three", id: "2.children[0].children[2]"}]}, {name: "Little Rabbit Son", id: "2.children[1]"}, {name: "Little Rabbit Daughter", id: "2.children[2]"}]}, {name: "Elephant", id: "3", children: [{name: "Little Elephant", id: "3.children[0]"}]}]
console .log (updateIds (testData [2] .children, 1))
.as-console-wrapper {min-height: 100% !important; top: 0}
Наряду с несколько более простой общей структурой этот код также заменяет ваши split
/ replace
/ join
инструкции одним regex.replace
.
Ни один из подходов не обновляет исходную структуру данных. Если вам нужно сделать это, вы можете присвоить этот результат обратно соответствующему пути в вашей структуре или создать функцию, которая делает эквивалент, при этом разделяя как можно больше структуры. Это не сложно. Функция assocPath
в недавнем ответе , вдохновленная Ramda , подойдет.