关于angular:使用@ ngrx / entity处理商店中的集合,getSelectors()不起作用

Using @ngrx/entity for handling collections in store, getSelectors() not working

我正在尝试使用@ ngrx / entity lib实现NgRx存储,但无法使用@ ngrx / entity getSelectors检索任何数据。 Redux Devtools正确显示了由Effect()加载的我的收藏集。所以我的效果正常工作。现在,我想使用adapter.getSelectors()函数中的selectAll选择器将数据选择为数组。我的减速机索引如下

减速器/ index.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);

减速机/模型.reducer.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 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());
  }
}

控制台显示错误

1
2
3
4
ModelsComponent.html:2
ERROR TypeError: Cannot read property 'ids' of undefined
at selectIds (entity.es5.js:45)
at eval (store.es5.js:572)

有什么建议或想法解决吗?谢谢!

UPDATE [请求的模板]

模板仅订阅models$可观察对象,与reduces模板相同。 model-card.component.ts只获取Input()和ng-content。

1
2
3
4
5
6
<app-model-card
  *ngFor="let model of models$ | async"
  [logo]="model.id"
  [routerLink]="[model.id]">
  {{model.title}}
</app-model-card>

更新[要求采取的措施]

actions / models.action.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;

模型效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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)))
        );
      })
    );
}


哦,该死,我知道了。 问题是createFeatureSelector,它仅选择功能(顾名思义)。 我将该模块注册为StoreModule.forFeature('configuration', reducers)

然后,解决方案是从功能选择器获取ConfigurationState,从默认选择器获取模型状态。

减速器/ index.ts

1
2
3
4
5
6
7
8
9
10
11
12
[...]
export const getConfigurationState = createFeatureSelector<ConfigurationState>('configuration');
export const getModelsState = createSelector(
  getConfigurationState,
  (configuration) => configuration.models
);

export const {
  selectIds,
  selectEntities,
  selectAll
} = fromModels.adapter.getSelectors(getModelsState);

感谢你的帮助!