Mamy prostą strukturę która odzwierciedla Menu. Najprostszy model danych to:
export interface Node {
nodes: Node[] | null; // albo Node[] albo null
expanded: boolean;
url: string | null;
}
I teraz w sytuacji gdy url któregoś z liści odpowiada jakiemuś konkretnemu url, trzeba zwrócić nowy Node
w którym wszystkie Node
są w sposób przechodni rodzicami dla danego Node
. Nie mogę update'ować starego ze względu na fakt, że potrzebuję zupełnie nowych obiektów. Kod który mam (okrojony, bez nullecheków, zrobiony pod konkretny przykład):
function expandLeaves(node: Node, url: string): Node {
const newLeaves = createNewLeaves(node.nodes!, url); // ! po zmiennej mówi kompilatorowi, że tam na 100% nulla nie będzie
return {
...node,
nodes: newLeaves,
expanded: newLeaves.some(leaf => leaf.expanded)
}
}
function createNewLeaves(nodes: Node[], url: string): Node[] {
return nodes.map(node => {
const expanded = node.nodes?.some(leaf => leaf.expanded) || node.url === url;
const newLeaves: Node[] | null = node.nodes ? createNewLeaves(node.nodes, url) : null;
return {
...node,
nodes: newLeaves,
expanded: expanded
}
})
}
Przykład:
{
"expanded":false,
"url":null,
"nodes":[
{
"url":"11",
"expanded":false,
"nodes":[
{
"expanded":false,
"url":"url"
}
]
}
]
}
Output:
{
"expanded":false, //powinno być true
"url":null,
"nodes":[
{
"url":"11",
"expanded":false, //powinno być true
"nodes":[
{
"expanded":true,
"url":"some-url",
"nodes":null
}
]
}
]
}
Jak widać, zmienia się ostatni - nie zmieniają się rodzice. Prawdopodobnie błąd wynika z tego, że do wywołania rekurencyjnego w funkcji zostaje przekazany "stary obiekt" który nie ma jeszcze zupdate'owanego pola expanded
więc url się nie zgadza oraz żaden leaf nie ma expanded === true
. Czy jest jakaś opcja, żeby przy generowaniu nowego Node
od razu zupdate'ować odpowiednie Node
? Jeśli tak, to potrzebowałbym tutaj pomocy z tym. Z góry dzięki :D