Pavel Poberezhnyi
Pavel Poberezhnyi

Reputation: 773

add new data inside redux state tree

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

Answers (3)

Yuya
Yuya

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

Ashot
Ashot

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

markerikson
markerikson

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

Related Questions