如何使用@ngrx / entity通过id选择单个对象

时间:2018-04-09 15:30:35

标签: angular ngrx ngrx-entity

使用@ngrx / entity我希望通过实体映射中的id数组按单个id或实体数组选择实体。

当实体集合获取新元素或实体项目发生更改时,我不希望触发组件内的选择订阅,我根本没有选择。

当我使用selectEntities选择器然后从结果中选择ID时,这显然发生在我身上。

那么如何从实体集合中选择1个或n个项目?

4 个答案:

答案 0 :(得分:2)

NgRx通过passing props as the last argument to a selector function支持参数化选择器

export const selectEntity = createSelector(
  selectEntities,
  (entities, props) => entities[props.id]
);

export const selectEntitiesByID = createSelector(
  selectEntities,
  (entities, props) => props.ids.map(id => entities[id])
);

这些调用完全符合您的预期:

this.store.pipe(
  select(selectEntity, { id: someID })
);

this.store.pipe(
  select(selectEntitiesByID, { ids: arrayOfIDs })
);

如果您的ID不变,则可以将其重构为工厂功能

export const selectEntity = id => createSelector(
  selectEntities,
  entities => entities[id]
);

export const selectEntitiesByID = ids => createSelector(
  selectEntities,
  entities => ids.map(id => entities[id])
);

因此被称为:

this.store.pipe(
  select(selectEntity(someID))
);

this.store.pipe(
  select(selectEntitiesByID(arrayOfIDs))
);

答案 1 :(得分:1)

除了entitiesids之外,我还在用户示例中为状态添加了selectedEntityId

import {User} from '../models/user.model';
import {EntityState, createEntityAdapter} from '@ngrx/entity';

export interface UsersState extends EntityState<User> {
  // additional entities state properties
  selectedUserId: number | null;
}

选择器如下所示:

export const selectUserEntities = selectEntities;

export const getSelectedUserId = (state: UsersState) => state.selectedUserId;

export const selectCurrentUser = createSelector(
  selectUserEntities,
  getSelectedUserId,
  (userEntities, userId) => userEntities[userId]
);

答案 2 :(得分:1)

不推荐使用带有 props 的选择器,有关详细信息,请参阅 RFC: Deprecate Selectors With Props

但是,RFC 2980 中演示了类型安全的替代方案。应用于@jordan-gray 的回答:

export const selectEntity = (props: { id: number }) =>
  createSelector(selectEntities, (entities) => {
    return entities[props.id];
  });

被调用

this.store.select(selectEntity({ id: myId }));

答案 3 :(得分:0)

对于这两种情况,我都会使用专用选择器处理它:

// single entity
export const singleEntitySelector = createSelector(

   // you should have set it up already 
   yourEntitiesObjSelector,

   // here I assume you have set up router reducer state or any other 
state slice where you keep single entity id
   yourIdSelector,

   // then you just return single entity as entities will be an object
   (entities, id) => entities[id]
);

// same for array (you will have to store selected ids also on the 
state tree)
export const selectedEntitiesArraySelector = createSelector(

   // you should have set it up already 
   yourEntitiesObjSelector,

   // here I assume you have set up selected ids store slice
   yourSelectedIdsArraySelector,

   // then you just return entities array reducing ids array
   (entities, idsArray) => idsArray.reduce((acc, id) => {
      return entities[id] ? [...acc, entities[id]] : acc;
   }, [])
);

然后,您将在组件中使用这些选择器,像往常一样使用async管道反映视图中的更改。它们将反映所有更改:要么是单个实体ID更改,要么是ids数组更改。除非组件中有一些额外的逻辑,否则不需要订阅任何内容。