Angular Ngrx 8 Ошибка селектора: невозможно прочитать свойство 'map' из неопределенного - PullRequest
0 голосов
/ 28 октября 2019

Я борюсь с Ngrx 8 Селекторов. Мне удалось запросить данные и сохранить их в хранилище, но я получаю эту ошибку «Не удается прочитать свойство« карта »неопределенного» всякий раз, когда я пытаюсь использовать селекторы.

Файл эффектов (ects-users.effects.ts)

import { Injectable } from '@angular/core';
import { Actions, ofType, createEffect } from '@ngrx/effects';
import { of } from 'rxjs';
import { map, catchError, switchMap } from 'rxjs/operators';

import * as fromExternalUsersActions from './external-user/external-user.actions';
import { UsersService } from '../../shared/services/crud/users.service';
import { ExternalUser } from './external-user/external-user.model';




@Injectable()
export class EctsUsersEffects {

  loadExternalUsersDetails$ = createEffect(() =>
    this.actions$
      .pipe(
        ofType(fromExternalUsersActions.initialLoadExternalUsers),
        switchMap(() =>
          this.externalUsersService.getAll()
            .pipe(
              map((externalUsers: any) => {
                const list: ExternalUser[] = externalUsers.payload;
                return fromExternalUsersActions.loadExternalUsers({ externalUsers: list });
              }),
              catchError(error => of(fromExternalUsersActions.loadExternalUsersFailure({ error })))
            ))
      ));






  constructor(private actions$: Actions, private externalUsersService: UsersService) { }

}

Файл действий (external-user.actions.ts)

import { createAction, props } from '@ngrx/store';
import { Update } from '@ngrx/entity';

import { ExternalUser } from './external-user.model';


export const initialLoadExternalUsers = createAction(
  '[ExternalUser/API] Initial Load ExternalUsers',
);

export const loadExternalUsersFailure = createAction(
  '[ExternalUser/API] Load ExternalUsers Failure',
  props<{ error: any }>()
);

export const loadExternalUsers = createAction(
  '[ExternalUser/API] Load ExternalUsers',
  props<{ externalUsers: ExternalUser[] }>()
);



export const addExternalUser = createAction(
  '[ExternalUser/API] Add ExternalUser',
  props<{ externalUser: ExternalUser }>()
);

export const upsertExternalUser = createAction(
  '[ExternalUser/API] Upsert ExternalUser',
  props<{ externalUser: ExternalUser }>()
);

export const addExternalUsers = createAction(
  '[ExternalUser/API] Add ExternalUsers',
  props<{ externalUsers: ExternalUser[] }>()
);

export const upsertExternalUsers = createAction(
  '[ExternalUser/API] Upsert ExternalUsers',
  props<{ externalUsers: ExternalUser[] }>()
);

export const updateExternalUser = createAction(
  '[ExternalUser/API] Update ExternalUser',
  props<{ externalUser: Update<ExternalUser> }>()
);

export const updateExternalUsers = createAction(
  '[ExternalUser/API] Update ExternalUsers',
  props<{ externalUsers: Update<ExternalUser>[] }>()
);

export const deleteExternalUser = createAction(
  '[ExternalUser/API] Delete ExternalUser',
  props<{ id: string }>()
);

export const deleteExternalUsers = createAction(
  '[ExternalUser/API] Delete ExternalUsers',
  props<{ ids: string[] }>()
);

export const clearExternalUsers = createAction(
  '[ExternalUser/API] Clear ExternalUsers'
);

Редуктор внешних пользователей (external-user.reducer.ts)

import { Action, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { ExternalUser } from './external-user.model';
import * as ExternalUserActions from './external-user.actions';

export const externalUsersFeatureKey = 'externalUsers';

export interface State extends EntityState<ExternalUser> {
  loaded: boolean;
  loading: boolean;
  ids: string[];
}

export const adapter: EntityAdapter<ExternalUser> = createEntityAdapter<ExternalUser>();

export const initialState: State = adapter.getInitialState({
  loaded: false,
  loading: false,
  ids: [],
});

const externalUserReducer = createReducer(
  initialState,
  on(ExternalUserActions.addExternalUser,
    (state, action) => adapter.addOne(action.externalUser, state)
  ),
  on(ExternalUserActions.upsertExternalUser,
    (state, action) => adapter.upsertOne(action.externalUser, state)
  ),
  on(ExternalUserActions.addExternalUsers,
    (state, action) => adapter.addMany(action.externalUsers, state)
  ),
  on(ExternalUserActions.upsertExternalUsers,
    (state, action) => adapter.upsertMany(action.externalUsers, state)
  ),
  on(ExternalUserActions.updateExternalUser,
    (state, action) => adapter.updateOne(action.externalUser, state)
  ),
  on(ExternalUserActions.updateExternalUsers,
    (state, action) => adapter.updateMany(action.externalUsers, state)
  ),
  on(ExternalUserActions.deleteExternalUser,
    (state, action) => adapter.removeOne(action.id, state)
  ),
  on(ExternalUserActions.deleteExternalUsers,
    (state, action) => adapter.removeMany(action.ids, state)
  ),
  on(ExternalUserActions.loadExternalUsers,
    (state, action) => adapter.addAll(action.externalUsers,
      {...state,
          loaded: true
      })
  ),
  on(ExternalUserActions.clearExternalUsers,
    state => adapter.removeAll(state)
  ),
);

export function reducer(state: State | undefined, action: Action) {
  return externalUserReducer(state, action);
}

export const getLoaded = (state: State) => state.loaded;

export const getLoading = (state: State) => state.loading;

export const getIds = (state: State) => state.ids;

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

Файл селекторов (external-users.selectors.ts)

import { createFeatureSelector, createSelector } from '@ngrx/store';
import { ectsUsersFeatureKey} from '../reducers';
import * as fromExternalUsers from './external-user.reducer';

export const selectExternalUsersState = createFeatureSelector<fromExternalUsers.State>(ectsUsersFeatureKey);

export const selectAllUsers = createSelector(
    selectExternalUsersState,
    fromExternalUsers.selectAll
);

export const selectExternalUsers = createSelector(
    selectAllUsers,
    externalUsers => {
        return externalUsers.filter(externalUser => !externalUser.user.isInternalUser);
    }
);

Файл общего редуктора (index.ts)

import {
  ActionReducerMap,
  MetaReducer
} from '@ngrx/store';
import { environment } from '../../../../environments/environment';
import * as fromExternalUser from '../external-user/external-user.reducer';
import * as fromOffice from '../office/office.reducer';

export const ectsUsersFeatureKey = 'ectsUsers';


export interface State {

  [fromExternalUser.externalUsersFeatureKey]: fromExternalUser.State;
  [fromOffice.officesFeatureKey]: fromOffice.State;
}

export const reducers: ActionReducerMap<State> = {

  [fromExternalUser.externalUsersFeatureKey]: fromExternalUser.reducer,
  [fromOffice.officesFeatureKey]: fromOffice.reducer,
};


export const metaReducers: MetaReducer<State>[] = !environment.production ? [] : [];

Ошибка, отображаемая на консоли

core.js:4002 ERROR TypeError: Cannot read property 'map' of undefined
    at entity.js:29
    at store.js:581
    at memoized (store.js:523)
    at defaultStateFn (store.js:550)
    at store.js:584
    at memoized (store.js:523)
    at store.js:581
    at memoized (store.js:523)
    at defaultStateFn (store.js:550)
    at store.js:584

Ответы [ 2 ]

0 голосов
/ 29 октября 2019

Я взломал его!

Я передал неправильное имя featureKey в файле external-users.selectors.ts Я изменил эту строку:

export const selectExternalUsersState = createFeatureSelector<fromExternalUsers.State>(ectsUsersFeatureKey);

на

export const selectExternalUsersState = createFeatureSelector<fromExternalUsers.State>(fromExternalUsers.externalUsersFeatureKey);

Затем импортировал ссылку на редуктор в модуль ects-users.module следующим образом:

StoreModule.forFeature(fromExternalUser.externalUsersFeatureKey, fromExternalUser.reducer),
0 голосов
/ 28 октября 2019

вы были на правильном пути, файл entity.js:29 должен иметь в этой строке следующее:

var selectAll = createSelector(selectIds, selectEntities, function (ids, entities) {
            return ids.map(function (id) { return entities[id]; });
        });

Это отображает текущие сущности из хранилища как массив, поскольку сущности являются jsonobject

ваша ошибка означает, что ваше состояние имеет переменную ids undefined, когда он всегда должен быть массивом (пустым или с идентификаторами)

Поскольку идентификаторы не определены, ids.mapВызовите исключение, которое вы получаете.

, чтобы решить эту проблему, я рекомендую вам установить Redux DevTools и открыть свою страницу в Chrome. Таким образом, вы сможете увидеть, что происходит в вашем состоянии, и какое отправленное действие установит для свойства ids значение undefined.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...