0
votes

I have a list of users and I need to get the roles for every user.

So I have an action LoadUserRole that takes an array of Users:

export class LoadUserRole implements Action {
  readonly type = UsersActionTypes.LoadUserRole;

  constructor(public payload: Array<User>) {}
}


export class LoadUserRoleSuccess implements Action {
  readonly type = UsersActionTypes.LoadUserRoleSuccess;

  constructor(public payload: { user: Update<User> }) {}
}

I'm using NgRx Effects to handle the side effect of calling the service :

 // Side Effect of the load users action
  @Effect()
  loadUserRole$ = this.actions$.pipe(
    ofType(UsersActionTypes.LoadUserRole),
    map((action: LoadUserRole) => action.payload),
    filter(users => users.length !== 0),
    map((users: User[]) => users.map((user: User) => user.id)),
    concatMap((ids: string[]) => ids.map((id: string) =>
        this.accountService
          .getAccountRole(id)
          .pipe(
            map((asset: any) => new LoadUserRoleSuccess({
              user: {
                id: asset.items[0].userId,
                changes: {
                  roleType: asset.items[0].roleType
                }
              }
            })),
            catchError(error => {
              return of(new LoadUserRoleFailure(error.message));
            })
          )
        )
      )
  );

The object given to LoadUserRoleSuccess is of type Update according to the Entity Adapter of NgRx Entity. So LoadUserRoleSuccess updates the user in the state, this works as I tested it with one user.

However this code gives me the error:

ERROR Error: Effect "UsersEffects.loadUserRole$" dispatched an invalid action: [object Object]

and

ERROR TypeError: Actions must have a type property

The account service nicely logs each id at once, but for some reason the dispatch of the success is not working, also the call to the backend is not made in the service.

What is the best way to handle this kind of situation?

here's my reducer function:

case UsersActionTypes.LoadUserRole: {
  return {
    ...state,
    pending: true,
  };
}

case UsersActionTypes.LoadUserRoleSuccess: {
  return usersAdapter.updateOne(action.payload.user, {
    ...state,
    pending: false,
  });
}
1
what does your LoadUserRoleSuccess look like? - dee zg
export class LoadUserRoleSuccess implements Action { readonly type = UsersActionTypes.LoadUserRoleSuccess; constructor(public payload: { user: Update<User> }) {} } - Sytham
Just a thought, but maybe it's resolved by simply replacing concatMap with mergeMap - Silvan Bregy
Nope, same error, thanks for commenting though - Sytham
Can you share your Action Type definitions - Okan Aslankan

1 Answers

0
votes

Since you are using map there, try this:


 map((asset: any) => of(new LoadUserRoleSuccess({
              user: {
                id: asset.items[0].userId,
                changes: {
                  roleType: asset.items[0].roleType
                }
              }
            }))),

of will make sure that it will return as an observable instead of an object