【问题标题】:How to define schema for recursive model with Normalizr如何使用 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
  • 好点,可能是因为会话名称相同吗?您是否尝试过在形状中定义和使用自我。

标签: javascript reactjs redux normalizr


【解决方案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" 完成了它,但是以这种方式访问​​私有道具似乎有点不合时宜。
    猜你喜欢
    • 2014-01-12
    • 2012-07-31
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    相关资源
    最近更新 更多