ngrx:如何将参数传递给createSelector方法中的选择器

时间:2018-11-29 19:17:44

标签: angular ngrx

商店中的状态非常简单:

const state = {
 records: [1,2,3],
};

我有一个记录选择器:

export const getRecords = createSelector(getState, (state: State) => state.records));

我现在想要的是具有单独的选择器,用于按索引获取每个记录。 为此,我想通过以下方式用道具创建一个通用选择器:

export const getRecordByIndex = createSelector(
getRecords,
(state: State, { index }) => state.records[index]),
);

然后创建几个特定的​​选择器e。 g。:

export const getFirstRecord = createSelector(
getRecordByIndex(/* somehow pass index = 0 to this selector */),
(firstRecord) => firstRecord),
);

但是当我们在createSelector方法中使用参数时,我没有发现如何将参数传递给带有道具的选择器。有可能吗?

7 个答案:

答案 0 :(得分:5)

来自此博客文章:https://blog.angularindepth.com/ngrx-parameterized-selector-e3f610529f8

  

从NgRx 6.1开始,选择器还接受一个额外的props参数。哪一个   意味着您现在可以定义一个选择器,如下所示:

this.m = 5;
for(var key in gui){
    if(!gui.hasOwnProperty(key)){
        if(gui[key].m == this.m-1){
            //something
        }
    }
}

啊...但是重新阅读您的问题,您是在问然后如何构建使用该选择器的另一个选择器?上面链接的文章建议构建工厂功能。

答案 1 :(得分:2)

我设法向选择器提供了参数,但使用方式略有变化。示例:

选择器(我在这里不使用其他功能)

export const selectReferentialsState = (state: AppState) => state.referentials;

export const referentialDataSelector = createSelector(
    selectReferentialsState,
    (state: ReferentialsState, props: { refType: Referential}) => state.data[props.refType]
);

用法

this.availableRoles$ = this.store.select(state => referentialDataSelector(state, { refType: Referential.Role}));

答案 2 :(得分:1)

这可以通过@timdeschryver 在他的 comment regarding the deprecation of props from ngrx selectors 中描述的“工厂选择器”来完成。

使用 OP 的请求,我将有以下实现:

export const getRecordByIndex = (index: number) => createSelector(
   getRecords, (records) => records[index]
);

然后可以用作:

const record$ = this.store.select(getRecordByIndex(1));

既然“使用带有道具的选择器”被标记为 Deprecated in the ngrx documentation,这似乎是首选方式。

答案 3 :(得分:0)

我正在使用"@ngrx/entity": "7.2.0",,并且可以看到将道具传递给每个选择器,例如,在我正在调用的组件中:

this.isActive$ = this.store.pipe(select(fromClient.isActive, { id: 'someid' }));

然后在我的减速器中,我有以下内容:

export const getClientState = createFeatureSelector<ClientState>('client');

export const getClient = createSelector(
  getClientState,
  (state, props) => {
    // do something with props.id to get the client then:
    return state;
  }
);

export const isActive: = createSelector(
  getClient, // props are passed to here
  (state: any) => { // i don't add the props argument here, as i don't need them
    return state.isActive;
  }
);

答案 4 :(得分:0)

使用固定的选择器参数可以正常工作:

this.counter = this.store.pipe(
    select(fromRoot.getCount, { multiply: 2 })
);

但是关于动态参数呢?

this.counter = this.store.pipe(
   select(fromRoot.getCount, { multiply: this.getMultiplier() })
);

getMultiplier() {
    ...
    return myUser.multiplier + magicFactor;
}

在我的应用中不起作用:-(((NgRx版本8)

答案 5 :(得分:0)

您可以使用投影仪功能:

export interface Record {
  // Some sort of record interface
}

export interface State {
  records: Record[];
}

export const getRecords = createSelector(
  getState,
  (state: State): Record[] => state.records)
);

export const getRecordByIndex = createSelector(
  getRecords,
  (records: Record[], { index }) => records[index]),
);

export const getFirstRecord = createSelector(
  getRecords,
  (records: Record[]) => getRecordByIndex.projector(records, { index: 0 })
);

答案 6 :(得分:0)

使用此库中的 mapSelectors reselect-mapper

看下面的例子

import { mapSelectors } from "reselect-mapper"

const getUserById = (state: State, id: string) => state.users[id]
const getPostByIndex = (state: State, index: number) => state.posts[index]

// now you can combine your selectors using mapSelectors
const getUserAndPost = mapSelectors({
         user: getUserById,
         post: getPostByIndex
      }, map => map); // map signature is { user: User, post: Post }
// getUserAndPost selector has the following signature
// (state: State, params: { user: string, post: number }) => ({ user: User, post: Post })