在 redux 状态树中添加新数据

Posted

技术标签:

【中文标题】在 redux 状态树中添加新数据【英文标题】:add new data inside redux state tree 【发布时间】:2016-09-29 22:44:39 【问题描述】:

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


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

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


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 子属性中粘贴子数组?

【问题讨论】:

我强烈推荐查看这个 redux 树示例 github.com/reactjs/redux/tree/master/examples/tree-view 【参考方案1】:

给定:

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

【讨论】:

是的,它会嵌套很深。你能附上一些可以匹配这种情况的递归函数的链接吗? 请给我一些时间。 @PavelPoberezhnyi 我添加了递归解决方案。 很抱歉,但无法理解什么是索引和 ids.slice(1) @PavelPoberezhnyi indiciesid 的列表,因此[1, 2, 3] 将使state.children[/* child with id = 1 */].children[/* child with id = 2 */].children[/* child with id = 3 */] 得到修改。 slice(1) 返回不带第一个元素的 indicies。这是递归函数的一般结构。如果你不熟悉递归的概念,你可以看一些像here 这样的例子。从本质上讲,您在达到某些基本情况的同时不断将相同的功能应用于自身。【参考方案2】:

Redux 存储中的关系或规范化数据的建议方法是以“规范化”方式组织它,类似于数据库表。这将使管理更新更容易。请参阅http://redux.js.org/docs/FAQ.html#organizing-state-nested-data、How to handle tree-shaped entities in Redux reducers? 和 https://github.com/reactjs/redux/pull/1269。

【讨论】:

【参考方案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`);
  

【讨论】:

返回数组的新实例不是最佳做法吗? 对不起@ctrlplusb 没有明白你的意思。你能澄清一下吗? @ctrlplusb 是的。所以它应该是 obj.children.concat('data got from server') 之类的东西,而不是在 if 语句中。 很抱歉,这可能是 3-d 或 4-th 级别。所以,如下所述,我必须编写一些递归函数

以上是关于在 redux 状态树中添加新数据的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL 如何取代 Redux

GraphQL 如何取代 Redux

Reactjs Redux 我们应该为状态树中的每个对象创建 sub reducer 吗?

将看不见的逻辑添加到只读状态 redux - 反应

尽管有异步计算,Redux 的最小状态?

为啥初始状态没有保留在 react-redux 中