使用@ngrx / entity我希望通过实体映射中的id数组按单个id或实体数组选择实体。
当实体集合获取新元素或实体项目发生更改时,我不希望触发组件内的选择订阅,我根本没有选择。
当我使用selectEntities选择器然后从结果中选择ID时,这显然发生在我身上。
那么如何从实体集合中选择1个或n个项目?
答案 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)
除了entities
和ids
之外,我还在用户示例中为状态添加了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数组更改。除非组件中有一些额外的逻辑,否则不需要订阅任何内容。