NGRX effect dispatched an invalid action

tprieboj picture tprieboj · Oct 5, 2018 · Viewed 8.6k times · Source

I am trying to create an @Effect() for my action. When I run action with type AuthenticationUserLoad I get an error.

ERROR Error: Effect "AuthenticationEffects.getUser$" dispatched an invalid action: [object Object]

Here is my Effect code

    @Effect()
      getUser$ = this.actions$.pipe(
       ofType(AuthenticationUserActions.AuthenticationUserTypes.AuthenticationUserLoad),
       map((action) => {

          return this.authService.getUser().pipe(
            map((user: User) => new AuthenticationUserActions.AuthenticationUserLoadSuccess({user})),
            catchError(error => of(new AuthenticationUserActions.AuthenticationUserLoadFailure({error})))

          );
        })
     );

UPDATE

I changed map to switchMap and it works.

 @Effect()
  getUser$ = this.actions$.pipe(
    ofType(AuthenticationUserActions.AuthenticationUserTypes.AuthenticationUserLoad),
    switchMap((action) => {

      return this.authService.getUser().pipe(
        map((user: User) => new AuthenticationUserActions.AuthenticationUserLoadSuccess({user})),
        catchError(error => of(new AuthenticationUserActions.AuthenticationUserLoadFailure({error})))
      );
    })
  );

Maybe I dont understand the difference between map and switchMap.

Answer

satanTime picture satanTime · May 29, 2020

map operator maps current value, it doesn't care whether it is an observable or not. Whereas switchMap or mergeMap or concatMap expect a callback to return an observable value, subscribe to it and emits its values.

Therefore when you call map you say that current value should be transformed to some other.

map(action => return this.authService.getUser()),
// here the value is an observable stream, but not its emits.

when you call switchMap you say now I want to subscribe to another stream and emit its values. Because it's switchMap it also says once the parent stream emits (the same action comes) unsubscribe from current child stream and subscribe again to what a new call of this.authService.getUser() returns.

switchMap(action => return this.authService.getUser()),
// here the value is an emit from this.authService.getUser() stream.