如何使用 Normalizr 定义递归模型的模式

Posted

技术标签:

【中文标题】如何使用 Normalizr 定义递归模型的模式【英文标题】:How to define schema for recursive model with Normalizr 【发布时间】:2017-05-21 06:22:06 【问题描述】:

在尝试规范化负载时遇到了一点问题,该负载包含与使用Normalizr的父级相同类型的嵌套架构

例如,我有一个初始对象 (menu),它有一个子对象 (sections),它是一个对象数组 (section),可以深入。


  id: 123,
  sections: [
    id: 1,
    sections:[ id: 4, sections: [ id: 5, sections: [] ] ]
  , 
    id: 2,
    sections:[]
  , 
    id: 3,
    sections:[]
  ]

我首先创建了一个 menu 架构,它的定义中的部分链接到一个 sections 架构,适用于第一次传递,但随后无法处理部分的子节点,因此我添加了一个后续section 架构中具有相同名称的定义(值得一试),但它不起作用。

const section = new schema.Entity('sections')

const sections = new schema.Entity('sections', 
  sections: section
)

const menu = new schema.Entity('menu',  
  sections: [ sections ]
)

section.define( sections )

我希望最终得到以下对象:


  entities: 
    menu: 
      sections: [1, 2, 3]
    ,
    sections: [
      1:  id: 1, sections: [4] ,
      2:  id: 2, sections: [] ,
      3:  id: 3, sections: [] ,
      4:  id: 4, sections: [5] ,
      5:  id: 5, sections: [] ,
    ]
  

【问题讨论】:

那不行吗?这看起来比我用过的语法要新,但我不明白为什么它不起作用。 如果它确实有效,我不会向 SO 发布问题! :D 好点,可能是因为会话名称相同吗?您是否尝试过在形状中定义和使用自我。 【参考方案1】:

如果有人有相同“类型”的嵌套对象的情况,例如“部分”,顶层结构也是“部分”的数组,如下所示:

const data = [
    
      id: 1,
      sections:[ id: 4, sections: [  id: 5, sections: []  ] ]
    , 
    
      id: 2,
      sections:[]
    , 
    
      id: 3,
      sections:[]
    
  ]

这里有一种“取消嵌套”它们的方法:

import schema, normalize from "normalizr";

const child = new schema.Entity("sections");
const sections = new schema.Array(child);
child.define(sections);

const topLevel = new schema.Entity("sections", 
    sections
);

const customSchema = [topLevel];

console.log(normalize(data, customSchema));

你会得到的是:


   "entities":
      "sections":
         "1":
            "id":1,
            "sections":[
               4
            ]
         ,
         "2":
            "id":2,
            "sections":[

            ]
         ,
         "3":
            "id":3,
            "sections":[

            ]
         ,
         "4":
            "id":4,
            "sections":[
               5
            ]
         ,
         "5":
            "id":5,
            "sections":[

            ]
         
      
   ,
   "result":[
      1,
      2,
      3
   ]

【讨论】:

【参考方案2】:

您的 sections 架构应该是 Array

const section = new schema.Entity('sections')
const sections = new schema.Array(section);
section.define( sections );
const menu = new schema.Entity('menu',  sections );

那么,在使用中……

const data = 
  id: 123,
  sections: [
    id: 1,
    sections:[ id: 4, sections: [  id: 5, sections: []  ] ]
  , 
    id: 2,
    sections:[]
  , 
    id: 3,
    sections:[]
  ]
;

normalize(data, menu)

将返回:


  "entities": 
    "sections": 
      "1":  "id": 1, "sections": [ 4 ] ,
      "2":  "id": 2, "sections": [] , 
      "3":  "id": 3, "sections": [] ,
      "4":  "id": 4, "sections": [ 5 ] ,
      "5":  "id": 5, "sections": [] 
    ,
    "menu": 
      "123":  "id": 123, "sections": [ 1, 2, 3 ] 
    
  ,
  "result": 123

【讨论】:

感谢 Paul,完全忽略了 schema.Array。很抱歉也发布了 Gitub 问题!感谢您的快速响应,周末愉快? 感谢您的这篇有用的帖子。如果***对象data 是一个部分数组,如何将该数组合并到相同的“entities.sections”对象中?在我的情况下不希望有menu @EliBaird 检查我添加的答案,希望对您有所帮助。 很棒的例子!但是,我有一些自定义部分 id,我们称它们为 sectionId 而不仅仅是 id。在schema.Entity() 上,可以使用ìdAttribute 添加option 参数来指定自定义ID,但在schema.Array 上似乎不可能,这会导致您的示例给出未定义的ID 值。有谁知道如何让您的递归数据示例与自定义 ID 一起使用?到目前为止,我已经通过sections.schema._idAttribute = "sectionId" 完成了它,但是以这种方式访问​​私有道具似乎有点不合时宜。

以上是关于如何使用 Normalizr 定义递归模型的模式的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 normalizr 解析 FractalTransformer

如何使用 normalizr 规范化来自 JSON 的数据?

如何使用“normalizr”规范化这个简单的 API 响应?

如何添加/删除使用 normalizr 生成的 redux 存储?

如何在 Jbuilder 和 Normalizr 之间展平数据

在 normalizr 中重命名结果属性