web-dev-qa-db-ja.com

@ ngrx / entityを使用してIDで単一のオブジェクトを選択する方法

@ ngrx/entityを使用して、エンティティマップから単一のIDでエンティティを選択するか、IDの配列でエンティティの配列を選択します。

エンティティコレクションが新しい要素を取得したとき、またはエンティティアイテムが変更されたときに、コンポーネント内の選択サブスクリプションがトリガーされないようにします。

これは明らかに、selectEntitiesセレクターを使用し、結果からIDを選択するときに発生します。

では、エンティティコレクションからIDで1個またはn個のアイテムを選択するにはどうすればよいですか?

9
vachee

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))
);
6
Jordan Gray

どちらのシナリオでも、専用のセレクターで処理します。

// 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配列の変更がありました。コンポーネントに追加のロジックがない限り、何もサブスクライブする必要はありません。

1
markoffden

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]
);
1
Colo Ghidini