@ ngrx/entityを使用して、エンティティマップから単一のIDでエンティティを選択するか、IDの配列でエンティティの配列を選択します。
エンティティコレクションが新しい要素を取得したとき、またはエンティティアイテムが変更されたときに、コンポーネント内の選択サブスクリプションがトリガーされないようにします。
これは明らかに、selectEntitiesセレクターを使用し、結果からIDを選択するときに発生します。
では、エンティティコレクションからIDで1個またはn個のアイテムを選択するにはどうすればよいですか?
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 })
);
IDが変更されない場合は、これらをfactory functionsにリファクタリングできます。
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))
);
どちらのシナリオでも、専用のセレクターで処理します。
// 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の変更またはID配列の変更がありました。コンポーネントに追加のロジックがない限り、何もサブスクライブする必要はありません。
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]
);