首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对状态中的递归嵌套数据进行建模

如何对状态中的递归嵌套数据进行建模
EN

Stack Overflow用户
提问于 2020-04-07 23:09:14
回答 1查看 485关注 0票数 0

我有一个类型如下的数据结构:

代码语言:javascript
复制
export interface IGroup {
  id: number;
  name: string;
  groupTypeId: number;
  items: IItem[];
  groups: IGroup[];

}

它递归地表示"Group“和"Group”以及"Group“和"Item”之间的多对多关系。组由项目和子组组成。项目只派生为简单类型和其他元数据,但不能有子项。单个组表示层次结构的顶层。

我目前有一些组件、钩子等可以递归地获取单个组并创建一个编辑/创建表单,如下所示:

我让这个表单“处理”测试数据,在保存时生成标准数据输出,如下所示:

代码语言:javascript
复制
{
  "1-1": {
    "name": "ParentGroup",
    "groupType": 2
  },
  "2-4": {
    "name": "ChildGroup1",
    "groupType": 1
  },
  "2-9": {
    "name": "ChildGroup2",
    "groupType": 3
  },
  "2-1": {
    "itemType": "FreeForm",
    "selectedName": "Testing",
    "selectedClass": 5
  },
  "2-2": {
    "itemType": "FreeForm",
    "selectedName": "DisplayTest",
    "selectedClass": 5
  },
  "3-4": {
    "itemType": "EnumValue",
    "selectedItem": {
      "id": 12900503,
      "name": "TRUE"
    }
  },
  "3-5": {
    "itemType": "EnumValue",
    "selectedItem": {
      "id": 12900502,
      "name": "FALSE"
    }
  },
  "3-9": {
    "itemType": "FreeForm",
    "selectedName": "Test",
    "selectedClass": 5
  },
  "3-10": {
    "itemType": "FreeForm",
    "selectedName": "Tester",
    "selectedClass": 5
  },
  "3-11": {
    "itemType": "FreeForm",
    "selectedName": "TestTest",
    "selectedClass": 5
  }
}

由于没有其他保证的唯一标识符(如果用户正在编辑,则期望组在db中具有in,但是如果用户在表单中添加新组则不是),所以这些对象的“关键”是网格列和行。否则,名称是可以更改的输入表单。)这是有意义的,并且很容易以这种方式对键进行建模。如果将另一个组或项目添加到层次结构中,则可以将其与其列和行一起添加。

我遇到的问题是,我希望能够有一个add按钮,它可以添加到组、项目或组数组中,这样就可以在层次结构中创建新的行。我的表单应该可以处理这些新条目。例如。

代码语言:javascript
复制
"1-1": {
  groups: [..., {}],
  items: [..., {}]
}

但我拥有的唯一数据结构是嵌套得很深的IGroup。这不利于使用as状态,也不适合添加到这种深度嵌套的状态中。

我的另一个问题是,我需要能够将项和组映射到它们的位置,以便我可以将多对多表转换到相应的数据库,并插入新的组/项。

建议的解决方案:我在想,我可以创建规范化的对象来存储状态,而不是将一个组放入我的递归组件中。我会有一个对象键控的列-行,它将容纳所有的组。另一个以列-行为关键字来保存所有项。然后我想我需要另外两个对象来保存多对多的关系,比如Group to Group和Group to Item。

在我从表单中获得数据后,我希望可以遍历这些状态对象,以这种方式找到层次结构,并将必要的数据发送到数据库。

我看到这是很多数据结构来保存这些数据,我不确定这是否是实现这一目标的最佳方式,因为我的建模结构。我也刚刚开始使用Redux Toolkit,所以我对Redux Toolkit比较熟悉,但还不足以让我明白如何在这里应用它们来帮助我。我真的一直在努力弄清楚这一点,任何帮助或指导,使这一点更容易,将非常感谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-10 16:17:43

请使用规范化。每个实体都有一个单一的真值来源,这使得读写状态变得容易得多。

要做到这一点,请尝试normalized-reducer。这是一个学习曲线较低的简单高阶降阶算法。

这是一个正在工作的CodeSandbox example of it,它实现了一个组/项复合树,与您的问题非常相似。

基本上,您将定义树的架构:

代码语言:javascript
复制
const schema = {
  group: {
    parentGroupId: { type: 'group', cardinality: 'one', reciprocal: 'childGroupIds' },
    childGroupIds: { type: 'group', cardinality: 'many', reciprocal: 'parentGroupId' },
    itemIds: { type: 'item', cardinality: 'many', reciprocal: 'groupId' }
  },
  item: {
    groupId: { type: 'group', cardinality: 'one', reciprocal: 'itemIds' }
  }
};

然后将其传递到库的顶级函数中:

代码语言:javascript
复制
import normalizedSlice from 'normalized-reducer';

export const {
  emptyState,
  actionCreators,
  reducer,
  selectors,
  actionTypes,
} = normalizedSlice(schema);

然后将reducer连接到您的应用程序中(与React useReducer和Redux store reducers一起使用),并使用selectorsactionCreators来读写状态。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61083273

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档