Redux + Normalizr:在Redux状态中添加和删除规范化实体

5

我有一个API响应,其中有许多嵌套实体。我使用normalizr尽可能使redux状态保持平整。


例如,API响应如下:

{
  "id": 1,
  "docs": [
    {
      "id": 1,
      "name": "IMG_0289.JPG"
    },
    {
      "id": 2,
      "name": "IMG_0223.JPG"
    }
  ],
  "tags": [
    {
      "id": "1",
      "name": "tag1"
    },
    {
      "id": "2",
      "name": "tag2"
    }
  ]
}

使用下面给出的模式,使用normalizr对此响应进行规范化:

const OpeningSchema = new schema.Entity('openings', {
    tags: [new schema.Entity('tags')],
    docs: [new schema.Entity('docs')]
});

以下是它的外观:

{
  result: "1",
  entities: {
    "openings": {
       "1": {
          "id": 1,
          "docs": [1,2],
          "tags": [1,2]
       }
    },
    "docs": { 
      "1": { 
        id: "1",
        "name": "IMG_0289.JPG"
      },
      "2": { 
        id: "2",
        "name": "IMG_0223.JPG"
      }
    },
    "tags": {
      "1": {
          "id": 1,
          "name": "tag1"
      },
      "2": {
          "id": 2,
          "name": "tag2"
      }
    }
  }
}

现在的redux状态大致如下:

state = {
  "opening" : {
      id: 1,
      tags: [1,2],
      docs: [1,2]
  },
  "tags": [
      {
          "id":1,
          "name": "tag1"
      },
      {
          "id":2,
          "name": "tag2"
      }
  ],
  "docs": [
      {
          "id":1,
          "name": "IMG_0289.JPG"
      },
      {
          "id":2,
          "name": "IMG_0223.JPG"
      }
  ]
}

现在,如果我派发一个添加tag的操作,那么它会将tag对象添加到state.tags中,但不会更新state.opening.tags数组。删除标签时也是同样的行为。
我将openingtagsdocs保存在三个不同的reducer中。
这是状态中的不一致性。我可以想到以下几种方法来保持状态的一致性:
  1. 我派发一个更新标签的操作,并在tags reducer和opening reducer中监听它,在两个地方都相应地更新标签。
  2. 用标签更新打开请求返回打开响应。我可以再次派发动作来规范化响应,并以适当的一致性设置标签、打开等。
什么是正确的做法?难道实体不应该观察相关实体的变化并自行进行更改吗?还是有其他的模式可以遵循任何这样的操作。

我知道这个问题已经几年了,但如果你仍然在reducers中规范化你的数据,请尝试使用:https://github.com/brietsparks/normalized-reducer - brietsparks
1个回答

5
首先,让我们总结一下normalizr的工作原理:将嵌套的API响应按照您定义的模式转换为实体。因此,当您进行初始的GET openings API请求时,normalizr会将响应扁平化,并创建Redux entities和扁平化的对象:openingsdocstags
您提出的建议是可行的,但我发现normalizr真正的好处在于将API数据与UI状态分离;因此,我不会自己更新Redux存储中的数据...所有我的API数据都保存在entities中,我不会对其进行更改;它们是纯粹的后端数据...我所做的只是在状态改变的API操作时执行GET,并规范化GET响应。对于DELETE情况有一个小例外,稍后我会详细介绍...一个中间件将处理这些情况,如果您还没有使用,请使用一个。我创建了自己的中间件,但我知道redux-promise-middleware非常受欢迎。
在上面的数据集中,当您添加新的tag时,我假设您正在进行API POST,从而更新后端。然后,您应该执行另一个GET openings,这将更新entities的openings及其所有嵌套模式。
当您删除一个tag,例如tag[2],在向后端发送DELETE请求之前,您应该将实体状态中已删除的对象置为空,即entities.tags[2] = null,然后再次执行GET openings以更新normalizr实体。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接