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

时间:2017-06-06 09:16:16

标签: redux react-redux normalizr redux-actions

我有一个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保留在三个不同的缩减器中。

这是州内的不一致。我可以想到以下方法来保持国家的一致性:

  1. 我发送了一个操作来更新标签,并在tags reducer和opening reducer中监听它,并随后在两个地方更新标签。
  2. 更新打开标签的补丁请求会返回打开响应。我可以再次发送操作,使响应标准化并设置标记,打开等,并保持适当的一致性。
  3. 这样做的正确方法是什么。不应该让实体观察相关实体的变化并自行进行更改。或者还有任何其他模式可以遵循任何此类行动。

1 个答案:

答案 0 :(得分:4)

首先总结一下normalizr的工作原理:normalizr展平对模式定义的实体的嵌套API响应。因此,当您提出初始GET openings API请求时,normalizr会将响应展平并创建Redux entities和展平对象:openingsdocstags

您的建议是可行的,但我发现normalizr在将API数据与UI状态分离方面确实有益;因此,我自己不会在Redux商店中更新数据......我的所有API数据都保存在entities中,并且我不会更改它们;它们是vanilla后端数据......我所做的就是在状态更改API操作时执行GET,并规范化GET响应。 DELETE案件有一个小例外,我稍后会对此进行扩展......中间件会处理此类情况,因此如果您还没有使用过,请使用一个。我创建了自己的中间件,但我知道redux-promise-middleware很受欢迎。

在您的数据集中;当您添加新的tag时,我假设您正在制作API POST,这样就会更新后端。然后,您应该执行另一个GET openings,这将更新entities的空缺及其所有嵌套模式。

删除tag时,例如tag [2],在向后端发送DELETE请求后,您应该使实体状态中的已删除对象无效,即。在再次entities.tags[2] = null更新您的normalizr实体之前GET openings。{/ p>