使用 @ngrx/entity 我想通过单个 id 选择实体或通过实体映射中的 id 数组选择实体数组。
我不希望在实体集合获得新元素或实体项更改时触发组件内的选择订阅,我根本没有选择。
当我使用 selectEntities 选择器然后从结果中选择 ID 时,这显然发生在我身上。
那么如何从实体集合中按 id 选择 1 或 n 项?
使用 @ngrx/entity 我想通过单个 id 选择实体或通过实体映射中的 id 数组选择实体数组。
我不希望在实体集合获得新元素或实体项更改时触发组件内的选择订阅,我根本没有选择。
当我使用 selectEntities 选择器然后从结果中选择 ID 时,这显然发生在我身上。
那么如何从实体集合中按 id 选择 1 或 n 项?
编辑:正如 Ethan 下面提到的,选择器props
在 v12 中被弃用。这个决定在 RFC 中得到了广泛的讨论。(进一步的评论讨论了如何有效地记忆工厂函数。)
目前推荐的方法是使用工厂函数:
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))
);
以前,NgRx 通过作为最后一个参数传递给选择器函数来支持参数化选择器:props
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 })
);
不推荐使用带有 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 }));
此外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]
);
对于这两种情况,我都会使用专用选择器来处理它:
// 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 数组变化。不需要订阅任何东西,除非你的组件中有一些额外的逻辑。