实际上我正在使用NGRX(Angular的Redux)。开始时,我开始将实体存储为状态内的数组。阅读一些文章后,我想将我的实体存储为散列,而我认为使用id而不是过滤数组来访问实体的实体更有效。
但是我实际上不确定以正确的ngrx方式进行操作。
可以在这里随意检查我的(正在工作-但是最佳做法?)示例: Ngrx Articles Sample
在articles.component内部,您将找到articleReducer和ArticlesComponent,它们将使用商店来获取所有文章并获得一份具体文章。
对于每个不确定的部分,我都有一个问题x-...
如果您不想检查完整的样本,请参见问题摘录:
问题0:
export const initialState: ArticleState = {
foo: 'bar',
articlesById: [], // QUESTION 0: What is a good usecase to hold an array with the id's when Object.keys(hash) will give the same?
articleEntities: {}
}
问题1 + 2:
case GET_ALL_ARTICLES: {
// QUESTION 1: is this a good choice? Or is there a better alternative to create the hash?
const articleHash: { [id: number]: Article} = {};
action.payload.forEach(article => articleHash[article.id] = article);
return {
...state,
// QUESTION 2: is this a good choice? Or is there a better alternative?
articlesById: action.payload.map(article => article.id),
articleEntities: articleHash
}
}
问题3:
// QUESTION 3 - Getting all articleEntities as Array for ngFor : is this a good choice? Or is there a better alternative?
this.articles$ = this.store.pipe(
select('articles', 'articleEntities'),
map(entities => Object.keys(entities).map(id => entities[id]))
);
问题4:
const givenIdByRouterMock = 2;
// QUESTION 4 - Getting one concrete Article for given id : is this a good choice? Or is there a better alternative?
this.article$ = this.store.pipe(
select('articles', 'articleEntities'),
map(entities => entities[givenIdByRouterMock])
);
如果我要使用新操作更新某些文章(例如ID为2的文章),我希望包含该文章的组件将被更新。
这是有效的变体还是有更好的选择和解决方案?随意将stackblitz示例与其他变体/代码段进行分叉。
谢谢!
答案 0 :(得分:2)
Q0::ids
属性可用于指示排序。另一点是,如果删除一个实体,仅将其从此数组中删除就足够了,与从字典中将其删除相比,这是一个比较简单的任务。
第一季度:您的解决方案有效,我更喜欢使用reduce
第二季度:很好
return {
products: action.payload.products.reduce((dict, product) => {
dict[product.sku] = product;
return dict;
}, {}),
productSkus: action.payload.products.map(product => product.sku),
};
Q3:,您确实应该将其转换为数组。如果您使用的是ids
属性(请参见答案1),则应使用ids.map(id => entities[id])
。
第4季度:确实要使用entities[id]
其他:
NgRx具有一个以这种方式处理状态的软件包@ngrx/entity-unsorted_state_adapter.ts-state_selectors.ts
代替使用this.store.pipe(select('articles', 'articleEntities'))
选择数据,我认为您应该看看NgRx selectors,它是更干净的恕我直言。
自Angular 6.1起,您还可以在具有键值管道的字典上使用ngFor
。
。
<mat-nav-list>
<a *ngFor="let member of familyMembers | async | keyvalue"
mat-list-item [routerLink]="['/groceries', member.key]">
{{ member.value.avatar }} {{member.value.name}}
</a>
</mat-nav-list>
答案 1 :(得分:1)
如果顺序很重要-将数组用作对象is not guaranteed中的属性顺序。 为了优化在Array中的查找,我们可以创建将Array转换为Object的选择器。 最好使状态规范化(无需保留我们可以从其他人计算出的值)。
linked
问题0:什么是用id的数组保存数组的好用例? Object.keys(hash)会给出相同的结果吗?
使用数组和将数组转换为对象的选择器
问题1:这是一个好选择吗?还是有更好的替代方法 创建哈希?
export interface ArticleState {
foo: string;
articles: Article[];
}
export const selectFeature = (state) => state.articleState;
export const selectFeatureArticles = createSelector(selectFeature, state => state.articles);
export const selectFeatureArticlesMap = createSelector(
selectFeatureArticles,
articles => _.keyBy(articles, 'id' )
);
action.payload.reduce((hash, article) =>({...hash, [article.id]: article}), {});
问题2:这是一个好选择吗?还是有更好的选择?
没关系。
问题3-将所有articleEntities作为ngFor的数组获取:是这个 一个好选择?还是有更好的选择?
将_.keyBy(action.payload, 'id' );
存储在数组中。
问题4-根据给定ID获取一篇具体文章:这是 好的选择?还是有更好的选择?
我没事。