Why should my Redux store be serializable?
Asked Answered
B

4

26

When reading the redux docs I found this:

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.

So my question is, what's the benefit of keeping state serializable? Or, what difficulties I may have if I put non-serializable data into store?

And I believe this is not unique to redux - Flux, even React local state suggest the same thing.


To make me clear here is an example. Suppose the store structure is like this.

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

This should all looks good. However when I try to access "the author of Book 1", I have to write code like this:

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

Now, I'm going to define a class:

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

And my store will be:

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

So that I can get the author easily by using:

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

The 2nd approach could make the "book" object aware of how to retrieve the author data, so the caller does not need to know the relation between books and authors. Then, why we are not using it, instead of keeping "plain object" in the store just as approach #1?

Any ideas are appreciated.

Bounty answered 2/12, 2016 at 21:28 Comment(1)
in JS you can make generic call/apply invocations, so such defs don't need to live in data, and one should separate data and logic anyway. make another abstraction layer if you want handy methodical goodies.Sin
E
34

Directly from 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.


Further reading:

Euphonium answered 2/12, 2016 at 21:55 Comment(3)
Thanks for the answer especially for mentioning time travel. This is new to me and it makes sense to keep the store serializable.Bounty
As author of the Redux FAQ, this is exactly why I wrote it :) Very happy to see people referencing it and using it to help answer questions!Scenarist
@Scenarist You did a great job with them, especially the collection of links to issues and third-party resources are really helpful!Euphonium
J
3

Adding to what @Timo said , If you want to setup relation between 2 states in your state tree and use computed values, reselect is the best suitable fit for that scenario. It allows to creareselectors which can be used to define computed states. In your case author can be created using a selector on top of book. https://github.com/reactjs/reselect

Janel answered 4/12, 2016 at 8:46 Comment(0)
S
1

@timo 's answer is correct. In addition, I recommend a library called Redux-ORM to work with normalized/relational data in your Redux store. See my recent comment at Dealing with data consistency in a very large store in React + Redux SPA SaaS for links to more information.

Scenarist answered 5/12, 2016 at 17:48 Comment(0)
A
0

Adding this because you asked for a suggestion. If you only want to create an object out of your class then you can simply create a function that returns an object. In your Book class it could be something like

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

And your store would look like

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

The object being returned can't contain any function's in it though, it should be just a plain static object with pure data and nothing else. You can't serialize something that isn't pure data.

Adnopoz answered 24/8, 2021 at 5:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.