Ngrx:结合两个选择器

时间:2017-04-06 13:43:56

标签: ngrx

我已经构建了这个IStore

export interface IStore {
  user: IUser;
  sources: ISourceRedux;
}

其中IUser是:

export interface IUser {
    id: string;
    cname: string;
    sname: string;
    ...
}

ISourceRedux是:

export interface ISourceRedux {
    entities: { [key: string]: ISource };
    ids: Array<string>;
    selectedIds: Array<string>;
    editingSource: ISource;
    defaultId: string;
}

所以,我创建了这些选择器:

export const getSourcesState = (state: IStore) => state.sources;
export const getSelectedIds = (sourceRdx: ISourceRedux) => sourceRdx.selectedIds;
export const getSelectedSourceIds = createSelector(getSourcesState, fromSources.getSelectedIds);

所以,到目前为止,为了检查用户是否已登录,我做到了:

this.store$
  .select(fromRoot.getUserState)
  .filter(user => user.id != null && user.logged)
  .do(user => this.store$.dispatch(...))
  ...

现在我正在努力获取用户信息和selectedSourceIds,以检查是否:

  1. 用户已登录(this.store$.select(fromRoot.getUserState)
  2. 然后获取所有selectedSourceIds(this.store.select(fromRoot.getSelectedSourceIds)
  3. 发送行动
  4. 我怎么能得到这个?

3 个答案:

答案 0 :(得分:6)

将代码添加到选择器是否有意义:

// Selector functions
const getProductFeatureState = createFeatureSelector<ProductState>('products');
const getUserFeatureState = createFeatureSelector<UserState>('users');

export const getCurrentProduct = createSelector(
  getProductFeatureState,
  getUserFeatureState,
  getCurrentProductId,
  (state, user, currentProductId) => {
    if (currentProductId === 0) {
      return {
        id: 0,
        productName: '',
        productCode: 'New',
        description: 'New product from user ' + user.currentUser,
        starRating: 0
      };
    } else {
      return currentProductId ? state.products.find(p => p.id === currentProductId) : null;
    }
  }
);

此代码在product.reducer文件中。在这里,我为产品和用户定义了功能选择器。

然后我同时使用产品和用户功能构建一个getCurrentProduct选择器。

答案 1 :(得分:4)

这是我的解决方案:

this.store$.combineLatest(
      this.store$.select(fromRoot.getUserEntity),
      this.store$.select(fromRoot.getSelectedSourceIds),
      (store, user, selectedSourceIds) => ({user: user, selectedSourceIds: selectedSourceIds}) 
    )
    .filter((proj) => proj.user.id != null && proj.user.logged)
    .do((proj) => this.store$.dispatch({type: 'DELETE_CARDS', payload: {username: proj.user.username, tokens: proj.selectedSourceIds}}))
    .take(1)
    .subscribe();

我希望它有用。

答案 2 :(得分:2)

我创建了一个特征选择器,它结合了两个特征来实现这一点。

全局模块的特征选择器:

export interface ScaffoldPartialState extends GlobalPartialState {
  readonly [SCAFFOLD_FEATURE_KEY]: State;
}

我将其导入 Scaffold 选择器并让 ScaffoldPartialState 对其进行扩展。

export interface ScaffoldPartialState extends GlobalPartialState {
  readonly [SCAFFOLD_FEATURE_KEY]: State;
}

createFeatureSelector 只返回输入的状态,因此返回的类型看起来只包含此功能的状态。
该值是完整的应用程序状态,但该类型使它看起来仅适用于一个模块。 通过一种类型扩展另一种类型,结果类型为两个模块提供了一个属性。

AppState

{
  module1: { ... },
  module2: { ... },
  module3: { ... }
}

Module2PartialState

{
  module2: { ... },
}

Module2PartialState extends Module3PartialState

{
  module2: { ... },
  module3: { ... }
}

这样 ScaffoldPartialState 功能选择器适用于两个模块的选择器。

示例:

export const getAuthorizedMenuItems = createSelector(
  getScaffoldState,
  GlobalSelectors.getUserPermissions,
  getMenuItems,
  (_globalState, userPermissions, menuItems) =>
    userPermissions ? menuItems.filter(e => userPermissions.checkAllPermissions(e.permissions)) : []
);