Reputation: 102
I'm trying to better understand the answer by Maxime to this question. My rep is not high enough to comment on the answer there, so I'll ask a new question here.
The part about setting up a normalized state makes sense. Then he goes on to talk about how you would create a selector, this part of his answer is quoted below, and showing his code block.
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])
}));
My question is, whether or not there is still a type definition of BlogContent
with an actualContent
array nested?
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[]; <------ NESTED
}
I don't quite understand what the selector getBlogContents
is doing and how this would be used in a component that wants to display blogContents with a nested list of actualContents, can this be explained in a little more detail?
Upvotes: 4
Views: 758
Reputation: 23803
@cartant pinged me on my original question so here I am (thx @cartant!).
I do think a lot about my interfaces within an app. I think it's important to have well defined interfaces or we'll end up with a mess :).
I've tried to create a basic pattern for it, as often, we end up with the same idea:
One resource:
- resource without details
- resource with details
- composed resource, where foreign keys with only IDs are replaced by corresponding resources
- composed resource with also UI variables (to show a state, for example fetching, downloading, etc)
A "table", which contains multiple of those resources:
- contains normalized data, with for example byId
and allIds
- contains some UI variables, this time not for every items, but the table (state for adding a resource would go there as the resource is not in the list yet for example)
I've made such a detailed example within angular-ngrx-starter
, here for the interfaces.
By the way, you might be interested by the whole folder, which is a complete example is this starter (actions, reducer, effects, interfaces ,selectors, service and mock for the service).
Hope it helps you understand but keep in mind that this is not perfect! It's just one way, my way of seeing things.
Upvotes: 3
Reputation: 2131
My question is, whether or not there is still a type definition of BlogContent with an actualContent array nested?
BlogContent only contains an array of ids for actualContent.
I don't quite understand what the selector getBlogContents is doing and how this would be used in a component that wants to display blogContents with a nested list of actualContents, can this be explained in a little more detail?
Maxime references his own project where he does a similar pattern.
Here's his selector: https://github.com/maxime1992/pizza-sync/blob/master/frontend/src/app/shared/states/orders/orders.selector.ts
Then he uses it here: https://github.com/maxime1992/pizza-sync/blob/b127ef963640d67f7560fad69f6f8364355ac697/frontend/src/app/features/order-summary-dialog/order-summary-dialog.component.ts
ngOnInit() {
this.orderSummary$ = this.store$.let(getOrderSummary);
}
Note that this is the old way to do selectors. The ngrx example app used to use it but they've refactored to use reselect.js for all selectors.
Upvotes: 1