我已经在EggHead上完成了Dan Abramov的简介系列,并且正在开发一个真实的应用程序。该域很复杂,因此我将以经典的“博客”示例为例。

假设我们有一个“索引/列表”页面,我们只需要显示博客文章的标题和内容即可。因此,我们有一个API端点返回该端点,并将其存储在状态树中的blogs.byId下。

然后,当您点击博客文章时,我们实际上需要更多信息-例如完整的博客文章,以及标签和类别。我们称其为“带有元数据的博客”。

扩展示例,可能会有另一个完全独立的页面,我要在其中显示最近发表3条评论的博客文章列表。我们称其为“带评论的博客”。

我的问题是,状态树应该如何处理这些单独的示例,这些示例以相同的方式存储相同的“事物”,但以不同的“格式”存储这些事物?我最初的直觉是将它们视为完全独立的数据类型,因此我的状态树将具有例如:blogs.byIdblogsWithMetadata.byIdblogsWithComments.byId

然后,即使每个博客帖子都缓存在blogs.byId部分中,也就是我们需要查看博客帖子的那一刻,该应用程序都会完全忽略该温暖的blogs.byId缓存,而只会查看blogsWithMetadata.byId-因此我们d本质上是建立3个独立的博客数据缓存,每个缓存具有不同的信息量,并将其视为与“博客”一样彼此无关,而将诸如“窗口小部件”这样的完全不相关的表视为一样。

它是否正确?或者,还有更好的方法?

该应用程序当前将它们全部都放在同一个节点下,没有根据“格式”进行区分,这引起了很多麻烦。

最佳答案

您可能有很多方法可以选择执行此操作。一种方法是使用normalizr来构造数据。

您的博客文章可能具有API返回的数据结构,如下所示:

{
  "id": "123",
  "author": {
    "id": "1",
    "name": "Paul"
  },
  "title": "My awesome blog post",
  "comments": [{
    "id": "324",
    "commenter": {
      "id": "2",
      "name": "Nicole"
    }
  }],
  "tags": [{
    "id": "1",
    "value": "awesome"
  }, {
    "id": "2",
    "value": "journal"
  }],
  "categories": [{
    "id": "1",
    "value": "personal"
  }, {
    "id": "2",
    "value": "life"
  }]
}


归一化后,它将看起来像这样:

{
  entities: {
    "post": {
      "123": {
        id: "123",
        author: "1",
        title: "My awesome blog post",
        comments: ["324"],
        tags: ["1", "2"],
        categories: ["1", "2"],
      }
    },
    "users": {
      "1": { "id": "1", "name": "Paul" },
      "2": { "id": "2", "name": "Nicole" }
    },
    "comments": {
      "324": { id: "324", "commenter": "2" }
    }
    "tags": {
      "1": { id: "1", "value": "awesome" },
      "2": { id: "2", "value": "journal" },
    }
    "categories": {
      "1": { id: "1", "value": "personal" },
      "2": { id: "2", "value": "life" },
    }
  }
}


随后,如果需要执行以下操作,则可以为每个页面提供状态:

{
  entities: {...},
  ui: {
    blogs: {
      posts: [1, 2],
      hasComments: false,
      // Displaying the blogs with or without comments
      // could simply just be a boolean flag in state.
    },
  }
}


然后使用reselect创建选择器,以将所需的道具传递给组件页面。

09-25 16:11