Thanks for the article Tim!
I’m curious about how to deal with nested data.
Let’s imagine that I have the following data model:
Book -> Author -> Address -> …
Each of which being a separate entity. From what I could understand so far, each of these entity types should be stored separately and normalized within the store, meaning that there’ll be a map of Books, a map of Authors and one for addresses.
Then, since we normalize the data, the object reference from book to author will be replaced by the id of the author when an entity of that type is added to the store.
Now my question is: how do we deal with the TypeScript types in all this to avoid duplicating type information and is it a good idea or not to try to reassemble the initial nested type when we take data out of the store or is that an anti-pattern (e.g., for performance and what not)?
Let’s look at an example.
If my book looks like this:
interface Book {
id: string;
name: string;
releaseDate: Date;
author: Author;
…
}
And the author like this:
interface Author {
id: string;
firstName: string;
givenName: string;
address: Address;
…
}
Then when I get a Book object within an effect for example, I might already need a first conversion step to create a serializable payload (since in this case there is a Date in Book that is not serializable).
If I do convert then it means that I already need a second data type to represent the converted Book object, but I guess that I can keep the Author and Address objects nested in the action payload and let the reducer take care of the normalization.
So my action payload might look something like this:
{
payload: {
book: SerializableBook;
}
Where the SerializableBook type might be defined like this to limit type information duplication
type SerializableBook = Exclude<’address’, ….> & { releaseDate: string; }(this is pseudocode but you get the idea)
Next, the reducer receives this payload and takes care of the normalization, meaning that we end up with a store structure like this:
{
books: {
ids: [ … ]
bookEntities: [ { … }, … ]
}
authors: { …}
…
}
At this point I want to retrieve some books out of the store, so I use selectors to get the books I want.
Now the question is: can/should the selector take care of re-assembling the initial Book object with references or should this be avoided, or should this assembling be handled at the smart component level?
Any ideas/pointers would be very welcome! :)