嵌套数据规范化 createEntityAdapter

Nested Data Normalization createEntityAdapter

我正在尝试规范化具有以下结构的数据数组 Array<Application>。使用 createEntityAdapter.

在使用 createAsyncThunk 获取数据并返回它们之后,我确实将它们设置在 extraReducers 中,如下所示:

applicationsAdapter.setAll(state, action.payload)

Redux DevTools 中,我可以看到数据如下所示:

{
    applications: {
      ids: [
        '60a684fb90957536f185ea88',
      ],
      entities: {
        '60a684fb90957536f185ea88': {
          id: '60a684fb90957536f185ea88',
          title: 'Article1',
          description: 'The best article ever',
          groups: [
            {
              id: 'bPDGd8uOkmKKAO3FyoTKE',
              title: 'Group 1',
              voters: [
                {
                  user: {
                    uid: '344bc9b8-671b-4de5-ab2d-a619ea34d0ba',
                    username: 'tran',
                  },
                  vote: 'DECLINED'
                }
              ]
            }
          ],
          deadline: "2021-05-20",
          budget: 0,
          createdAt: '2021-05-20',
          createdBy: {
            uid: 'ab2a8f19-c851-4a5f-9438-1000bfde205a',
            username: 'admin',
          },
     },
}

问题: 数据未完全标准化。如何规范化组、投票者和用户对象?

接口如下:

export interface Application {
    id: string;
    title: string;
    description: string;
    groups: Array<GroupElement>;
    deadline: string;
    budget?: number;
    createdAt: string;
    createdBy: User;
}


export interface GroupElement {
    id: string;
    title: string;
    voters: Array<Voter>;
}

export interface User {
    uid: string;
    username: string;
}

export interface Voter {
    user: User;
    vote: Decision;
}

createEntityAdapter 不会自行执行任何类型的关系规范化。您需要为此使用 normalizr

由于 Voter 对象缺少自己的 id 属性,因此很难规范化。我不得不拼凑一个。

import { schema, normalize } from "normalizr";

const user = new schema.Entity("user", {}, { idAttribute: "uid" });

const voter = new schema.Entity(
  "voter",
  {
    user: user
  },
  {
    idAttribute: (object) => `${object.vote}-${object.user.uid}`
  }
);

const group = new schema.Entity("group", {
  voters: [voter]
});

const application = new schema.Entity("application", {
  createdBy: user,
  groups: [group]
});

normalize(entity, application);

这会将您的数据转换为:

{
  "entities": {
    "user": {
      "ab2a8f19-c851-4a5f-9438-1000bfde205a": {
        "uid": "ab2a8f19-c851-4a5f-9438-1000bfde205a",
        "username": "admin"
      },
      "344bc9b8-671b-4de5-ab2d-a619ea34d0ba": {
        "uid": "344bc9b8-671b-4de5-ab2d-a619ea34d0ba",
        "username": "tran"
      }
    },
    "voter": {
      "DECLINED-344bc9b8-671b-4de5-ab2d-a619ea34d0ba": {
        "user": "344bc9b8-671b-4de5-ab2d-a619ea34d0ba",
        "vote": "DECLINED"
      }
    },
    "group": {
      "bPDGd8uOkmKKAO3FyoTKE": {
        "id": "bPDGd8uOkmKKAO3FyoTKE",
        "title": "Group 1",
        "voters": ["DECLINED-344bc9b8-671b-4de5-ab2d-a619ea34d0ba"]
      }
    },
    "application": {
      "60a684fb90957536f185ea88": {
        "id": "60a684fb90957536f185ea88",
        "title": "Article1",
        "description": "The best article ever",
        "groups": ["bPDGd8uOkmKKAO3FyoTKE"],
        "deadline": "2021-05-20",
        "budget": 0,
        "createdAt": "2021-05-20",
        "createdBy": "ab2a8f19-c851-4a5f-9438-1000bfde205a"
      }
    }
  },
  "result": "60a684fb90957536f185ea88"
}

我同意你的看法。 createEntityAdapter 似乎进行第一层规范化,因此输出“ids / entities”。我不确定将它与 normalizr 一起使用是可行的方法,因为 createEntityAdapter 的 API 公开了一些将数据放回其中的方法,例如 addONe 或 addMany,如果您将它与 normalizr 一起使用以规范化嵌套数据,我不会不认为您可以使用最外层的方法,例如 addOne 或 Addmany 用于您使用库 (normalizr) 规范化的嵌套方法。