Reputation: 773
I have an app with a tree of nested nodes. all nodes are same type.
{
id: 1,
title: "node_1",
children: [
{
id: 2,
title: "node_2",
children: []
},
{
id: 3,
title: "node_3",
children: []
}
]
}
When user expanded some node (for example node with id === 3) i have to perform request to database and insert response (array children) inside of "children" property of node with id === 3 . So as result app state should be like this:
{
id: 1,
title: "node_1",
children: [
{
id: 2,
title: "node_2",
children: []
},
{
id: 3,
title: "node_3",
children: [
{
id: 4,
title: "node_4",
children: []
},
{
id: 5,
title: "node_5",
children: []
}
]
}
]
}
how can i paste array of children inside node_3 children property?
Upvotes: 0
Views: 1138
Reputation: 2311
Given:
const layer1Id = 1;
const layer2Id = 3;
const newArray = [
{
id: 4,
title: "node_4",
children: [],
},
{
id: 5,
title: "node_5",
children: [],
}
];
Then, in the reducer you'll do:
return Object.assign({}, state, { children: state.children.map(child => {
if (child.id !== layer1Id) return child;
return Object.assign({}, child, { children: child.children.map(node => {
if (node.id !== layer2Id) return node;
return Object.assign({}, node, { children: node.children.concat(newArray) });
})});
})});
To make sure you don't mutate the previous state. If it is dynamically or deeply nested, I'll recommend you to write some recursive function and use that instead.
Edit: here's sample recursive solution (untested). The indices
are in order by level (ie: indices[0]
refers to first level's id, indices[1]
refers to second level's id):
const state = { ... };
const indices = [1, 3, 4, 5, 6];
const newArray = [ ... ];
const recursion = (node, ids, newChildren) => {
let children;
if (ids.length === 0) {
children = newChildren;
} else {
children = node.children.map(child => {
if (child.id !== ids[0]) return child;
return Object.assign({}, child, { children: recursion(child, ids.slice(1), newChildren) });
});
}
return Object.assign({}, node, { children });
};
recursion(state, indecies, newArray);
Upvotes: 1
Reputation: 1299
Just iterate through children
array and push to correct one .
var id = expandedItemId;
for(var i = 0; i < obj.children.length; i++){
if(obj.id == expandedItemId){
obj.children.push(`data got from server`);
}
}
Upvotes: -1
Reputation: 67627
The suggested approach for relational or normalized data in a Redux store is to organize it in "normalized" fashion, similar to database tables. That will make it easier to manage updates. See http://redux.js.org/docs/FAQ.html#organizing-state-nested-data, How to handle tree-shaped entities in Redux reducers?, and https://github.com/reactjs/redux/pull/1269.
Upvotes: 1