【问题标题】:NGRX - Using hashes instead of arrays for stateNGRX - 使用散列而不是数组来表示状态
【发布时间】:2018-09-15 21:13:15
【问题描述】:

实际上我正在使用 NGRX(Redux for Angular)。一开始我已经开始将我的实体作为数组存储在我的状态中。在阅读了一些文章后,我想将我的实体存储为哈希值,而我认为使用 id 访问实体实体而不是过滤数组会更高效。

但我实际上不确定这样做是否正确。

请随时在此处查看我的(工作 - 但最佳实践?)示例: Ngrx Articles Sample

在articles.component 中,您会找到articleReducer 和ArticlesComponent,它们将使用商店来获取所有文章并获取一篇具体文章。

对于每个不确定的部分,我都会用 QUESTION 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 示例与其他变体/代码 sn-ps 分叉。

谢谢!

【问题讨论】:

    标签: angular redux ngrx


    【解决方案1】:

    Q0:ids 属性可用于指示排序。另一点是,如果您删除一个实体,只需将其从 this 数组中删除就足够了,与从字典中删除它相比,这是一项更简单的任务。

    Q1:您的解决方案有效,我更喜欢使用 reduce

    Q2:没关系

    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])

    Q4:确实要选择特定实体使用entities[id]

    额外:

    .

    <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>
    

    【讨论】:

    • 您好@timdeschryver,您的回答很好。谢谢你的额外提示。尤其是“从 Angular 6.1 开始,您还可以在带有键值管道的字典上使用 ngFor。”很高兴知道。我想,我必须检查 reduce 功能。实际上并不是 100% 清楚,它是如何工作的。您的 Q3 答案的一个问题:您将如何通过存储“id”数组和带有实体的字典来选择?您是执行 2 次选择并合并它们还是选择整个状态?
    • 好的,我想我可以自己回答我的问题:阅读 NgRx 选择器的提示后,我还检查了 NgRx 的示例应用程序,因此我找到了使用 NgRx 选择器的组合示例.
    • 太棒了 :) 如果不清楚,请随时通过 gitter 验证您的想法。
    【解决方案2】:

    如果顺序很重要 - 使用数组作为对象 is not guaranteed 中的属性顺序。 为了优化 Array 中的查找,我们可以创建将 Array 转换为 Object 的选择器。 最好保持状态标准化(不需要保留我们可以从其他人计算的值)。

    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' )
    );
    

    问题 0:什么是一个很好的用例来保存一个带有 id 的数组 when Object.keys(hash) 会给出同样的结果吗?

    使用数组和选择器将数组转换为对象

    问题 1:这是一个好的选择吗?或者有没有更好的选择 创建哈希?

    action.payload.reduce((hash, article) =>({...hash, [article.id]: article}), {});
    

    Lodash keyBy

    _.keyBy(action.payload, 'id' );

    问题 2:这是一个好的选择吗?还是有更好的选择?

    没关系。

    问题 3 - 将所有 articleEntities 作为 ngFor 的数组:这是 一个不错的选择?还是有更好的选择?

    articles 存储在数组中。

    问题 4 - 为给定的 id 获取一篇具体的文章:这是一个 好的选择?还是有更好的选择?

    我不好。

    【讨论】:

    • 嗨@Buggy,你能解释一下,你的陈述中的“acc”是什么? --> "action.payload.reduce((hash, article) =>({...hash, [article.id]: article}), acc);"实际上,reduce 方法对我来说并不是 100% 清楚。
    • 谢谢,我的意思是累加器的初始值,它正在输入,正在编辑。
    猜你喜欢
    • 2018-07-06
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多