簡體   English   中英

如何使用@ngrx/entity 通過 id 選擇單個對象

[英]How to select a single object by id using @ngrx/entity

使用@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 不會改變,您可以將它們重構為工廠函數

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))
);

除了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]
);

對於這兩種情況,我都會使用專用選擇器來處理它:

// 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 數組更改。 不需要訂閱任何東西,除非你的組件中有一些額外的邏輯。

不推薦使用帶有道具的選擇器,有關更多信息,請參閱RFC:不推薦使用帶有道具的選擇器

但是, RFC 2980 中演示了類型安全的替代方案。 應用於@jordan-gray 的回答:

export const selectEntity = (props: { id: number }) =>
  createSelector(selectEntities, (entities) => {
    return entities[props.id];
  });

this.store.select(selectEntity({ id: myId }));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM