0

How to fix: 'TypeError: entities not iterable' in ngRx? I am new in using ngrx functionality just referring this URL - https://www.youtube.com/watch?v=igc5rBN50wk&list=PLaMbwDs23r4KXoMucJEyUAvamQ-kFNBvC&index=7

user.effects.ts

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

import { UserActionTypes, LoadUserAction, LoadUserSuccessAction, LoadUserFailureAction, UpdateUserAction,
    UpdateUserSuccessAction, UpdateUserFailureAction, DeleteUserAction, DeleteUserSuccessAction,
    DeleteUserFailureAction} from '../actions/user.actions';
import { UserService } from 'src/app/core/services/user.service';
import { UserGraphqlService } from 'src/app/core/services/user-graphql.service';
import { User } from 'src/app/shared/models/user.model';

// Effects perform operation base on any action called by components or services
@Injectable()
export class UserEffects {

    constructor(private actions$: Actions,
                private userService: UserService,
                private userGraphqlService: UserGraphqlService) { }

    @Effect()
    loadUser$ = this.actions$.pipe(
        ofType<LoadUserAction>(UserActionTypes.LOAD_USER),
        mergeMap(() => this.userService.sendUserQueryRequest(this.userGraphqlService.getUserListGraphqlString()).pipe(
            map((data: User[]) => {
                return new LoadUserSuccessAction(data);
            }),
            catchError(error => of(new LoadUserFailureAction(error)))
        ))
    );
}

problem is in load user listing user.reducers.ts


import { createFeatureSelector, createSelector } from '@ngrx/store';
import { User } from 'src/app/shared/models/user.model';
import { UserAction, UserActionTypes } from '../actions/user.actions';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';

export interface UserState extends EntityState<User> {
    selectedCustomerId: number | null;
    loading: boolean;
    error: Error;
}

export const userAdapter: EntityAdapter<User> = createEntityAdapter<User>();
export const defaultUser: UserState = {
ids: [],
entities: {},
selectedCustomerId: null,
loading: false,
error: undefined
};
// Define intialstate value of app state
export const initialState = userAdapter.getInitialState(defaultUser);

// Change store app state as per actions
export function UserReducer(state: UserState = initialState, action: UserAction) {
    switch (action.type) {
        case UserActionTypes.LOAD_USER:
            return {
                ...state,
                loading: true
            };

        case UserActionTypes.LOAD_USER_SUCCESS:
            return userAdapter.addAll(action.payload, {
                ...state,
                // list: action.payload,
                loading: false
            });

        case UserActionTypes.LOAD_USER_FAILURE:
            return {
                ...state,
                entities: {},
                error: action.payload,
                loading: false
            };
        case UserActionTypes.UPDATE_USER:
            return {
                ...state,
                loading: true
            };
        case UserActionTypes.UPDATE_USER_SUCCESS:
            return {
                ...state,
                entities: {},
                loading: false
            };
        case UserActionTypes.UPDATE_USER_FAILURE:
            return {
                ...state,
                error: action.payload,
                loading: false
            };
        case UserActionTypes.DELETE_USER:
            return {
                ...state,
                loading: true
            };
        case UserActionTypes.DELETE_USER_SUCCESS:
            return {
                ...state,
                entities: {},
                // list: {
                //     ...state.list,
                //     Users: JSON.parse(JSON.stringify(state.list)).Users.
                //           filter(item => item.Username !==
                //           JSON.parse(JSON.stringify(action.payload)).Username)
                // },
                loading: false
            };
        case UserActionTypes.DELETE_USER_FAILURE:
            return {
                ...state,
                error: action.payload,
                loading: false
            };
        default:
            return state;
    }
}


const getUserFeatureState = createFeatureSelector<UserState>('user');

// This selector use to fetch all users
export const getUsers = createSelector(
    getUserFeatureState,
    userAdapter.getSelectors().selectAll,
);

// This selector use to fetch loading value
export const getUsersLoading = createSelector(
    getUserFeatureState,
    (state: UserState) => state.loading
);

// This selector use to fetch error value
export const getError = createSelector(
    getUserFeatureState,
    (state: UserState) => state.error
);

// This selector use to fetch specific users base on id
export const getUser = (id: string ) => createSelector(
    getUserFeatureState,
    userAdapter.getSelectors().selectAll,
    // (state: UserState) => {
    //     const jsonResponse = JSON.parse(JSON.stringify(state.list));
    //     if (jsonResponse && jsonResponse.Users && jsonResponse.Users.length > 0) {
    //         const selectedUser = jsonResponse.Users.filter(user => user.Username === id)[0];
    //         return selectedUser;
    //     } else {
    //         return {};
    //     }
    // }
);

user.actions.ts

import { Action } from '@ngrx/store';
import { User } from 'src/app/shared/models/user.model';

// Define all possible action types base on action reducer change state
export enum UserActionTypes {
    LOAD_USER = '[User] Load User',
    LOAD_USER_SUCCESS = '[User] Load User Success',
    LOAD_USER_FAILURE = '[User] Load User Failure',

    UPDATE_USER = '[User] Update User',
    UPDATE_USER_SUCCESS = '[User] Update User Success',
    UPDATE_USER_FAILURE = '[User] Update User Failure',

    DELETE_USER = '[User] Delete User',
    DELETE_USER_SUCCESS = '[User] Delete User Success',
    DELETE_USER_FAILURE = '[User] Delete User Failure',

}

// Use when load all the users
export class LoadUserAction implements Action {
    readonly type = UserActionTypes.LOAD_USER;
}

// Use when getting successful all user data
export class LoadUserSuccessAction implements Action {
    readonly type = UserActionTypes.LOAD_USER_SUCCESS;
    constructor(public payload: Array<User>) { }
}

// Use when getting an error while loading user data
export class LoadUserFailureAction implements Action {
    readonly type = UserActionTypes.LOAD_USER_FAILURE;
    constructor(public payload: Error) { }
}
// Update User
export class UpdateUserAction implements Action {
    readonly type = UserActionTypes.UPDATE_USER;
    constructor(public payload: User) { }
}
// Update User Success
export class UpdateUserSuccessAction implements Action {
    readonly type = UserActionTypes.UPDATE_USER_SUCCESS;
    constructor(public payload: User) { }
}

// Update User Failure
export class UpdateUserFailureAction implements Action {
    readonly type = UserActionTypes.UPDATE_USER_FAILURE;
    constructor(public payload: Error) { }
}

// Delete User
export class DeleteUserAction implements Action {
    readonly type = UserActionTypes.DELETE_USER;
    constructor(public payload: User) { }
}
// Delete User Success
export class DeleteUserSuccessAction implements Action {
    readonly type = UserActionTypes.DELETE_USER_SUCCESS;
    constructor(public payload: User) { }
}

// Delete User Failure
export class DeleteUserFailureAction implements Action {
    readonly type = UserActionTypes.DELETE_USER_FAILURE;
    constructor(public payload: Error) { }
}


export type UserAction = LoadUserAction | LoadUserSuccessAction |
                         LoadUserFailureAction | UpdateUserAction | UpdateUserSuccessAction | UpdateUserFailureAction |
                         DeleteUserAction | DeleteUserSuccessAction | DeleteUserFailureAction;

user.graphql.service.ts

import { Injectable } from '@angular/core';

@Injectable({
    providedIn: 'root'
})

export class UserGraphqlService {

    getUserListGraphqlString() {
        return `query {
            listUsers {
              Users {
                  Attributes {
                      Name,
                      Value
                    },
                    UserCreateDate,
                    UserLastModifiedDate,
                    Username,
                    UserStatus,
                    Group,
                    Enabled
                },
              user_pool_id,
              user_name,
              group_name,
              message,
              result
            }
          }`;
    }
}

where, user.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';
import { map, mergeMap, catchError } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})
// Use to fetch data from the server
export class UserService {

    private URL = '';

    constructor(private http: HttpClient) {
        this.URL = environment.URL;
    }

    sendUserQueryRequest(data) {
        return this.http.post<any>(this.URL + '/query', data).pipe(map(val => val.data.listUsers));
    }
    deleteUserQueryRequest(data) {
        return this.http.post<any>(this.URL + '/query', data).pipe(map(val => val.data.deleteUser));
    }
}

getting an error

core.js:6014 ERROR TypeError: entities is not iterable
    at addManyMutably (http://localhost:4200/users-users-module.js:214:30)
    at setAllMutably (http://localhost:4200/users-users-module.js:227:9)
    at Object.operation [as addAll] (http://localhost:4200/users-users-module.js:149:27)
    at UserReducer (http://localhost:4200/users-users-module.js:3033:32)
    at http://localhost:4200/vendor.js:267485:20
    at combination (http://localhost:4200/vendor.js:267373:37)
    at http://localhost:4200/vendor.js:268249:27
    at http://localhost:4200/vendor.js:267453:20
    at computeNextEntry (http://localhost:4200/vendor.js:266247:21)
    at recomputeStates (http://localhost:4200/vendor.js:266300:15)
halfer
  • 19,824
  • 17
  • 99
  • 186
sanny
  • 3
  • 5
  • Please read [Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers?](//meta.stackoverflow.com/q/326569) - the summary is that this is not an ideal way to address volunteers, and is probably counterproductive to obtaining answers. Please refrain from adding this to your questions. – halfer Jul 02 '20 at 09:56

1 Answers1

0

Change this

// This selector use to fetch specific users base on id
export const getUser = (id: string ) => createSelector(
    getUserFeatureState,
    userAdapter.getSelectors().selectAll,
    // (state: UserState) => {
    //     const jsonResponse = JSON.parse(JSON.stringify(state.list));
    //     if (jsonResponse && jsonResponse.Users && jsonResponse.Users.length > 0) {
    //         const selectedUser = jsonResponse.Users.filter(user => user.Username === id)[0];
    //         return selectedUser;
    //     } else {
    //         return {};
    //     }
    // }
);

to this:

// This selector use to fetch specific users base on id
export const getUser = (id: string ) => createSelector(
    getUsers,
    (users) => users.find( user => user.id === id)
);

And use the entity adapter to set the state. ex.

case ABC:
 return userEntityAdapter.addMany({...state, loading: false}, action.payload.users);
 

You can find some examples here.

Anarno
  • 1,470
  • 9
  • 18