在 redux 状态树中添加新数据

add new data inside redux state tree

我有一个带有嵌套节点树的应用程序。所有节点都是同一类型。

{
id: 1,
title: "node_1",
children: [
    {
        id: 2,
        title: "node_2",
        children: []
    },
    {
        id: 3,
        title: "node_3",
        children: []
    }
]

}

当用户扩展某些节点(例如 id === 3 的节点)时,我必须对数据库执行请求并在节点的 "children" 属性 内插入响应(子数组)编号 === 3 。所以结果应用程序状态应该是这样的:

{
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: []
            }
        ]
    }
]

}

如何将子数组粘贴到 node_3 子 属性 中?

只需遍历 children 数组并推送到更正一个 .

var id = expandedItemId; 
for(var i = 0; i < obj.children.length; i++){
  if(obj.id == expandedItemId){
     obj.children.push(`data got from server`);
  }
}

对于 Redux 存储中的关系或规范化数据,建议的方法是以 "normalized" 方式组织它,类似于数据库表。这将使管理更新变得更加容易。参见 http://redux.js.org/docs/FAQ.html#organizing-state-nested-data, , and https://github.com/reactjs/redux/pull/1269

鉴于:

const layer1Id = 1;
const layer2Id = 3;
const newArray = [
  {
    id: 4,
    title: "node_4",
    children: [],
  },
  {
    id: 5,
    title: "node_5",
    children: [],
  }
];

然后,在减速器中你会做:

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) });
  })});
})});

确保您不会改变之前的状态。 如果它是动态或深度嵌套的,我会建议你写一些递归函数来代替它。

编辑:这是示例递归解决方案(未经测试)。 indices按级别排序(即:indices[0]表示一级id,indices[1]表示二级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);