Using @ngrx/entity I want to select an entity by a single id or an array of entities by an array of ids from an entity map.
I do not want the select subscriptions inside a component to be triggered when the entity collection gets a new element or an entity item changes, which I did not select at all.
This obviously happens to me when I use the selectEntities selector and then pick the IDs from the result.
So how can I select 1 or n items by id from an entity collection?
business data, such as for example Courses or Lessons, in the case of an online course platform. some UI state, such as for example UI user preferences.
Quoting NgRx Data documentation, typical usage of this library is entity data management. Basically it means that if you have complex entity collection you should go hard way and use @ngrx/entity where the boilerplate code is huge.
Selectors are pure functions used for obtaining slices of store state. @ngrx/store provides a few helper functions for optimizing this selection. Selectors provide many features when selecting slices of state: Portability.
EDIT: as Ethan mentions below, selectors with props
were deprecated in v12. This decision was discussed extensively in an RFC. (Comments further down the thread address how to effectively memoise factory functions.)
The currently recommended approach to this is using a factory function:
export const selectEntity = id => createSelector(
selectEntities,
entities => entities[id]
);
export const selectEntitiesByID = ids => createSelector(
selectEntities,
entities => ids.map(id => entities[id])
);
Which are called thus:
this.store.pipe(
select(selectEntity(someID))
);
this.store.pipe(
select(selectEntitiesByID(arrayOfIDs))
);
Previously, NgRx supported parameterised selectors by 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])
);
These are invoked exactly as you might expect:
this.store.pipe(
select(selectEntity, { id: someID })
);
this.store.pipe(
select(selectEntitiesByID, { ids: arrayOfIDs })
);
Selectors with props are deprecated, for more info see RFC: Deprecate Selectors With Props.
However, a type safe alternative is demonstrated in RFC 2980. Applied to the answer from @jordan-gray:
export const selectEntity = (props: { id: number }) =>
createSelector(selectEntities, (entities) => {
return entities[props.id];
});
Called with
this.store.select(selectEntity({ id: myId }));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With