NGRX 从有效的参数化选择器获取状态
NGRX Get State from Parameterized Selector in Effect
背景
我有一个用于搜索的 NGRX 商店,如下所示:
export interface State {
field: string;
operator: string;
criteria: string;
offset: number;
limit: number;
}
并且因为我多次使用 Search,所以我在我的主状态对象中创建了这个 Search 状态的多个实例:
// In index.ts
export interface State {
search: {
main: searchReducer.State;
other: searchReducer.State;
};
}
以及一个参数化的选择器以获得正确的选择器:
export const chooseSearchInstance = (instance: string): ((state: State) => searchReducer.State) => {
switch(instance) {
case 'MAIN': {
return getMainSearchState;
}
case 'OTHER': {
return getOtherSearchState;
}
}
};
问题
我正在尝试对搜索进行一些分页,因此我需要在 Effect 中使用上面的选择器才能知道它是否仍然是相同的搜索。然而,由于 "withLatestFrom" 只需要一个额外的 Observable 源而不是回调,我不确定我将如何在 Effect 中指定它?
@Effect()
public searchItems: Observable<Action> = this.actions.pipe(
ofType<searchActions.PerformSearchAction>(searchActions.PERFORM_SEARCH),
withLatestFrom(this.store.select(rootReducers.chooseSearch( action.payload.instance)), // <-- Cannot do this since there is no access to action at this point.
switchMap(([action, searchState] => (/* ... */))
);
我还尝试使用直接使用 this.store.select 的 mergeMap,但它导致了无限循环,因为这种效果最终会修改触发 mergeMap 中的选择器的状态。
那么我如何获得要在此 Effect 中使用的搜索状态的特定实例? (如果有更好的方法来表示同一类型状态的不同实例,我想我也会接受说整个实例想法是错误的答案)。
我在尝试访问 withLatestFrom
中的操作时遇到了完全相同的问题,这就是我解决它的方法:
// Same as withLatestFrom but used mergeMap/forkJoin because of use of action.payload
mergeMap((action) => forkJoin(
of(action),
this.store.pipe(select(rootReducers.chooseSearch(action.payload.instance)), take(1)),
)),
switchMap([action, searchState] => (/* ... */))
请注意 take(1)
的使用,否则根据我的经验,代码将挂起,它只是从参数化选择器中获取值。它在没有它的情况下挂起,因为我认为 forkJoin
等待所有 Observables 完成,并且 take(1)
进行一次发射然后完成。
背景
我有一个用于搜索的 NGRX 商店,如下所示:
export interface State {
field: string;
operator: string;
criteria: string;
offset: number;
limit: number;
}
并且因为我多次使用 Search,所以我在我的主状态对象中创建了这个 Search 状态的多个实例:
// In index.ts
export interface State {
search: {
main: searchReducer.State;
other: searchReducer.State;
};
}
以及一个参数化的选择器以获得正确的选择器:
export const chooseSearchInstance = (instance: string): ((state: State) => searchReducer.State) => {
switch(instance) {
case 'MAIN': {
return getMainSearchState;
}
case 'OTHER': {
return getOtherSearchState;
}
}
};
问题
我正在尝试对搜索进行一些分页,因此我需要在 Effect 中使用上面的选择器才能知道它是否仍然是相同的搜索。然而,由于 "withLatestFrom" 只需要一个额外的 Observable 源而不是回调,我不确定我将如何在 Effect 中指定它?
@Effect()
public searchItems: Observable<Action> = this.actions.pipe(
ofType<searchActions.PerformSearchAction>(searchActions.PERFORM_SEARCH),
withLatestFrom(this.store.select(rootReducers.chooseSearch( action.payload.instance)), // <-- Cannot do this since there is no access to action at this point.
switchMap(([action, searchState] => (/* ... */))
);
我还尝试使用直接使用 this.store.select 的 mergeMap,但它导致了无限循环,因为这种效果最终会修改触发 mergeMap 中的选择器的状态。
那么我如何获得要在此 Effect 中使用的搜索状态的特定实例? (如果有更好的方法来表示同一类型状态的不同实例,我想我也会接受说整个实例想法是错误的答案)。
我在尝试访问 withLatestFrom
中的操作时遇到了完全相同的问题,这就是我解决它的方法:
// Same as withLatestFrom but used mergeMap/forkJoin because of use of action.payload
mergeMap((action) => forkJoin(
of(action),
this.store.pipe(select(rootReducers.chooseSearch(action.payload.instance)), take(1)),
)),
switchMap([action, searchState] => (/* ... */))
请注意 take(1)
的使用,否则根据我的经验,代码将挂起,它只是从参数化选择器中获取值。它在没有它的情况下挂起,因为我认为 forkJoin
等待所有 Observables 完成,并且 take(1)
进行一次发射然后完成。