Reputation: 147
I am stuck at the task of traversing a tree and replacing the nodes if they match the key. This is necessary as I load children lazy via REST, insert them into the parent node and then replace the parent node (The node I clicked onto) with the parent with loaded children.
The treeData interface is:
export interface TreeData {
keyNum:number,
icon:string,
name:string,
length:number,
type: string,
links: string,
children?: TreeData[]
}
_nodes = Temp array that replaces the current nodes
nodes = All elements
event = Current parent
test = Temporary array for pushing items when doing it recursively
In a first attempt I created this function:
let _nodes = nodes.map(node => {
if (node.keyNum=== event.keyNum) {
node = event;
}
return node;
})
setNodes(_nodes)
Unfortunately this doesn't do this recursively. Only when I open up the root item. In a next attempt I created this function:
const test = [] as TreeData[]
traverseTree(event,nodes, test)
dispatch(setNodes(test))
const traverseTree = (event: TreeData, currentNodes: TreeData[], temp: TreeData[])=>{
currentNodes.forEach(node=>{
if (node.keyNum === event.keyNum) {
node = event;
temp.push(node)
}
else{
if(node.children && node.children.length>0){
return node.children.forEach(nodeInLoop=>{
return traverseTree(event,[nodeInLoop], temp)
})
}
}
})
}
I can finally traverse the tree but the problem is that when I click element1
-root
- element 1
- element 2
this gets transformed to:
- element 1
- subelement 1
- subelement 2
- ...
So when I click a child everything above is replaced. How can I preserve also the parent when clicking element 1. So that the expected output is
- root
- element 1
- subelement 1
- subelement 2
- ...
- element 2
Upvotes: 0
Views: 61
Reputation: 350290
I would not use a third parameter like in your recursive code. Instead make the function return the new tree.
It is indeed a problem that in your attempt the only thing that happens to temp
is that nodes are pushed unto it. But you'll also need to repopulate children
arrays in the hierarchy. You can better use map
for that, and spread syntax to clone nodes with newly created children
arrays.
Your recursive attempt could be corrected like this:
const traverseTree = (event: TreeData, nodes: TreeData[]): TreeData[] =>
nodes.map(node =>
node.keyNum === event.keyNum ? event
: !node.children?.length ? node
: { ...node, children: traverseTree(event, node.children) };
);
Call like:
dispatch(setNodes(traverseTree(event,nodes)))
Upvotes: 1