I am learning the redux pattern and using ngrx with angular 2. I am creating a sample blog site which has following shape.
Instead of having a nested structure
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[]; <------ NESTED
}
You should have a normalized state.
For example here you should have something like :
// this should be into your store
export interface BlogContents {
byId: { [key: string]: BlogContent };
allIds: string[];
}
// this is made to type the objects you'll find in the byId
export interface BlogContent {
id: string;
// ...
actualContentIds: string[];
}
// ----------------------------------------------------------
// this should be into your store
export interface ActualContents {
byId: { [key: string]: ActualContent };
allIds: string[];
}
export interface ActualContent {
id: string;
// ...
}
So if you try to populate your store it'd look like that :
const blogContentsState: BlogContents = {
byId: {
blogContentId0: {
id: 'idBlogContent0',
// ...
actualContentIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
}
},
allIds: ['blogContentId0']
};
const actualContentState: ActualContents = {
byId: {
actualContentId0: {
id: 'actualContentId0',
// ...
},
actualContentId1: {
id: 'actualContentId1',
// ...
},
actualContentId2: {
id: 'actualContentId2',
// ...
}
},
allIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
};
In your logic or view (for example with Angular), you need your nested structure so you can iterate over your array and thus, you don't want to iterate on a string array of IDs. Instead you'd like actualContent: ActualContent[];
.
For that, you create a selector
. Every time your store change, your selector will kicks in and generate a new "view" of your raw data.
// assuming that you can blogContentsState and actualContentsState from your store
const getBlogContents = (blogContentsState, actualContentsState) =>
blogContentsState
.allIds
.map(blogContentId => ({
...blogContentsState.byId[blogContentId],
actualContent: blogContentsState
.byId[blogContentId]
.actualContentIds
.map(actualContentId => actualContentsState.byId[actualContentId])
}));
I know it can be a lot to process at the beginning and I invite you to read the official doc about selectors and normalized state
As you're learning ngrx, you might want to take a look into a small project I've made called Pizza-Sync. Code source is on Github. It's a project were I've done something like that to demo :). (You should also definitely install the ReduxDevTools app to see how is the store).
I made a small video focus only on Redux with Pizza-Sync if you're interested : https://youtu.be/I28m9lwp15Y