【问题标题】:Why should my Redux store be serializable?为什么我的 Redux store 应该是可序列化的?
【发布时间】:2017-04-17 21:18:31
【问题描述】:

阅读 redux 文档时,我发现:

不过,您应该尽最大努力保持状态可序列化。 不要在里面放任何你不能轻易转换成 JSON 的东西。

所以我的问题是,保持状态可序列化有什么好处? 或者,如果我将不可序列化的数据放入存储中,我可能会遇到什么困难?

而且我相信这不是 redux 独有的 - Flux,甚至 React 本地状态也暗示了同样的事情。


为了让我清楚,这里是一个例子。假设商店结构是这样的。

{
    books: { 
        1: { id: 1, name: "Book 1", author_id: 4 }
    },
    authors: {
        4: { id: 4, name: "Author 4" }
    }
}

这一切看起来都不错。但是,当我尝试访问“Book 1 的作者”时,我必须编写如下代码:

let book = store.getState().books[book_id];
let author = store.getState().authors[book.author_id];

现在,我要定义一个类:

class Book {
    getAuthor() {
        return store.getState().authors[this.author_id];
    }
}

我的商店将是:

{
    books: {
        1: Book(id=1, name="Book 1")
    },
    ...
}

这样我可以很容易地通过使用获得作者:

let author = store.getState().books[book_id].getAuthor();

第二种方法可以使“书”对象知道如何检索作者数据,因此调用者不需要知道书籍和作者之间的关系。那么,为什么我们不使用它,而不是像方法 1 一样将“普通对象”保留在存储中?

感谢任何想法。

【问题讨论】:

  • 在 JS 中,您可以进行通用调用/应用调用,因此此类定义不需要存在于数据中,并且无论如何都应该分离数据和逻辑。如果您想要方便的有条不紊的好东西,请创建另一个抽象层。

标签: javascript reactjs redux flux


【解决方案1】:

直接来自the redux FAQs

我可以将函数、承诺或其他不可序列化的项目放入我的商店状态吗?

强烈建议您只将普通的可序列化对象、数组和原语放入您的存储中。在技​​术上可以将不可序列化的项目插入到存储中,但这样做会破坏存储内容的持久化和再水化能力,并干扰时间旅行调试。

如果您对持久性和时间旅行调试等可能无法按预期工作的事情感到满意,那么完全欢迎您将不可序列化的项目放入您的 Redux 存储中。最终,它是您的应用程序,您如何实现它取决于您。与有关 Redux 的许多其他事情一样,请确保您了解所涉及的权衡。


进一步阅读:

【讨论】:

  • 感谢您的回答,尤其是提到时间旅行。这对我来说是新的,保持 store 可序列化是有意义的。
  • 作为 Redux 常见问题解答的作者,这正是我写它的原因:) 很高兴看到人们引用它并使用它来帮助回答问题!
  • @markerikson 你和他们一起做得很好,尤其是问题链接和第三方资源的收集真的很有帮助!
【解决方案2】:

除了@Timo 所说,如果您想在状态树中设置两个状态之间的关系并使用计算值,reselect 最适合该场景。它允许 creareselectors 可用于定义计算状态。在您的情况下,author 可以使用book 之上的选择器创建。 https://github.com/reactjs/reselect

【讨论】:

    【解决方案3】:

    @timo 的回答是正确的。此外,我推荐一个名为 Redux-ORM 的库来处理 Redux 存储中的规范化/关系数据。请参阅我最近在Dealing with data consistency in a very large store in React + Redux SPA SaaS 的评论以获取更多信息的链接。

    【讨论】:

      【解决方案4】:

      添加此内容是因为您要求提供建议。如果您只想从类中创建一个对象,那么您可以简单地创建一个返回对象的函数。在您的 Book 课程中,它可能类似于

      function newBookObject({id, name}) {
          return {id, name}
      }
      

      你的商店看起来像

      {
          books: {
              1: newBookObject({id: 1, name: "Book 1"})
          },
          ...
      }
      

      返回的对象不能包含任何函数,它应该只是一个纯静态对象,包含纯数据,没有其他内容。你不能序列化不是纯数据的东西。

      【讨论】:

        猜你喜欢
        • 2021-02-13
        • 2010-11-07
        • 2020-02-02
        • 2011-07-24
        • 1970-01-01
        • 1970-01-01
        • 2022-12-22
        • 1970-01-01
        相关资源
        最近更新 更多