使用 @ngrx/entity 处理商店中的集合,getSelectors() 不起作用
Posted
技术标签:
【中文标题】使用 @ngrx/entity 处理商店中的集合,getSelectors() 不起作用【英文标题】:Using @ngrx/entity for handling collections in store, getSelectors() not working 【发布时间】:2018-10-02 14:56:41 【问题描述】:我正在尝试使用 @ngrx/entity lib 实现 NgRx 存储,但我无法使用 @ngrx/entity getSelectors 检索任何数据。 Redux Devtools 将 Effect() 加载的我的集合正确地显示为实体。所以我的效果工作正常。现在我想通过使用来自adapter.getSelectors()
函数的selectAll
选择器来选择数据作为数组。我的 reducer 索引如下所示
reducers/index.ts
import ActionReducerMap, createFeatureSelector, createSelector from '@ngrx/store';
import * as fromModels from './models.reducer';
import EntityState from '@ngrx/entity';
export interface State
models: fromModels.State;
export const reducers: ActionReducerMap<State> =
models: fromModels.reducer
;
export const getModelsState = createFeatureSelector<fromModels.State>('models');
export const selectAll: getAllModels = fromModels.adapter.getSelectors(getModelsState);
reducers/models.reducer.ts
import createFeatureSelector, createSelector from '@ngrx/store';
import createEntityAdapter, EntityState, EntityAdapter from '@ngrx/entity';
import ModelsActions, ModelsActionTypes from '../actions';
import Model from '../../models/model';
export const adapter: EntityAdapter<Model> = createEntityAdapter<Model>(
selectId: model => model.id,
sortComparer: (modelA, modelB) => modelA.id === modelB.id ? 0 : (modelA.id === modelB.id ? 1 : -1)
);
export interface State extends EntityState<Model>
const initialState = adapter.getInitialState();
export function reducer(state = initialState, action: ModelsActions): State
switch (action.type)
case ModelsActionTypes.LoadSuccess:
return adapter.addAll(action.payload, state);
default: return state;
在我的容器组件中,我想通过 ngrx/entity 选择器选择数据并使用异步管道显示数据。 (我缩小了模板)
models.component.ts
// All other import statements
import Store, select from '@ngrx/store';
import * as fromFeature from '../store';
@Component(
template: `models$ | async | json`
)
export class ModelsComponent implements OnInit
models$: Observable<Model[]>;
constructor(private store: Store<fromFeature.State>)
ngOnInit()
this.models$ = this.store.select(fromFeature.getAllModels);
this.store.dispatch(new fromFeature.LoadModels());
控制台打印错误
ModelsComponent.html:2
ERROR TypeError: Cannot read property 'ids' of undefined
at selectIds (entity.es5.js:45)
at eval (store.es5.js:572)
有解决这个问题的建议或想法吗?谢谢!
更新 [请求的模板]
模板只订阅models$
observable,与reduce模板中的相同。 model-card.component.ts 只获取 Input() 和 ng-content。
<app-model-card
*ngFor="let model of models$ | async"
[logo]="model.id"
[routerLink]="[model.id]">
model.title
</app-model-card>
更新 [请求的操作]
actions/models.action.ts
import Action from '@ngrx/store';
import Model from '../../models/model';
export enum ModelsActionTypes
Load = '[Models] Load',
LoadSuccess = '[Models] Load Success',
LoadFailed = '[Models] Load Failed'
export class LoadModels implements Action
readonly type = ModelsActionTypes.Load;
export class LoadModelsSuccess implements Action
readonly type = ModelsActionTypes.LoadSuccess;
constructor(public payload: Model[])
export class LoadModelsFailed implements Action
readonly type = ModelsActionTypes.LoadFailed;
constructor(public payload: any)
export type ModelsActions =
LoadModels |
LoadModelsSuccess |
LoadModelsFailed;
models.effects.ts
import Injectable from '@angular/core';
import Actions, Effect from '@ngrx/effects';
import Observable from 'rxjs/Observable';
import of from 'rxjs/observable/of';
import map, switchMap, catchError from 'rxjs/operators';
import ModelsActionTypes, LoadModelsSuccess, LoadModelsFailed from
'../actions';
import ModelsService from '../../services/models.service';
@Injectable()
export class ModelsEffects
constructor(
private actions$: Actions,
private modelsService: ModelsService
)
@Effect()
loadModels$ = this.actions$
.ofType(ModelsActionTypes.Load)
.pipe(
switchMap(() =>
return this.modelsService.getModels().pipe(
map(models => new LoadModelsSuccess(models)),
catchError(error => of(new LoadModelsFailed(error)))
);
)
);
【问题讨论】:
请提供ModelsComponent.html的内容。 @DiabolicWords 更新了我的问题附加模板。无法想象错误在模板中。缩小的模板会导致同样的错误。 可能是this.models$ = this.store.select(fromFeature.getAllModels)
-> this.models$ = this.store.select(fromFeature.selectAll)
?
@RichardMatsen 不起作用,同样的错误。
我注意到'./models.reducer'
但reducers/model.reducers.ts
- 但这肯定是问题中的错字,对吧?
【参考方案1】:
哦,该死的,我想通了。问题是createFeatureSelector
,它只是选择功能(正如它的名字所说)。我将模块注册为StoreModule.forFeature('configuration', reducers)
然后解决方案是从功能选择器中获取 ConfigurationState,从默认选择器中获取模型状态。
reducers/index.ts
[...]
export const getConfigurationState = createFeatureSelector<ConfigurationState>('configuration');
export const getModelsState = createSelector(
getConfigurationState,
(configuration) => configuration.models
);
export const
selectIds,
selectEntities,
selectAll
= fromModels.adapter.getSelectors(getModelsState);
感谢您的帮助!
【讨论】:
我这样做了,但仍然遇到同样的错误。有什么解决办法吗? 需要有关您的问题和代码的更多信息,此解决方案适用于我。创建一个问题或 stackblitz 让我知道。 我想通了,我的状态界面有问题,因此无法选择所需的状态。谢谢。以上是关于使用 @ngrx/entity 处理商店中的集合,getSelectors() 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
[NgRx] NgRx Entity Adapter Configuration - Understanding sortComparer and selectId