为什么我的 Redux store 应该是可序列化的?

Why should my Redux store be serializable?

在阅读 redux 文档时我发现了这个:

Still, you should do your best to keep the state serializable. Don't put anything inside it that you can't easily turn into JSON.

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

而且我相信这不是 redux - Flux 独有的,甚至 React 本地状态也有同样的建议。


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

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

这看起来应该不错。但是,当我尝试访问“第一本书的作者”时,我必须编写如下代码:

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

现在,我要定义一个 class:

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 那样在商店中保留“普通对象”?

欢迎任何想法。

直接来自the redux FAQs

Can I put functions, promises, or other non-serializable items in my store state?

It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. It's technically possible to insert non-serializable items into the store, but doing so can break the ability to persist and rehydrate the contents of a store, as well as interfere with time-travel debugging.

If you are okay with things like persistence and time-travel debugging potentially not working as intended, then you are totally welcome to put non-serializable items into your Redux store. Ultimately, it's your application, and how you implement it is up to you. As with many other things about Redux, just be sure you understand what tradeoffs are involved.


进一步阅读:

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

@timo 的回答是正确的。此外,我推荐一个名为 Redux-ORM to work with normalized/relational data in your Redux store. See my recent comment at 的库以获取更多信息的链接。

添加此内容是因为您征求了建议。如果您只想从 class 创建一个对象,那么您可以简单地创建一个 returns 对象的函数。在你的书中 class 它可能类似于

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

你的商店看起来像

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

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