Angular router navigation inside NgRx effect

rbasniak picture rbasniak · May 28, 2018 · Viewed 13.3k times · Source

Does the Angular router have any restrictions to be used inside an NgRx effect?

I just started learning NgRx and I have the following code:

@Effect() public authenticate$ = this.actions$
    .ofType(authenticationActions.AUTHENTICATE)
        .switchMap((action: AuthenticateAction) => this.authenticationService.authenticate(action.payload)
            .map((data: TokenData) => {
                const user: User = {
                    token: data.token,
                    username: 'dummy',
                };
                console.log(data);
                this.router.navigateByUrl('/');
                return new authenticationActions.AuthenticateSuccessAction(user);
            })
            .catch(error => { console.log(error); return Observable.throw(error); })
        );

The console logs the data variable and the AuthenticateSuccessAction action is being triggered, so the router line is being executed but the navigation doesn't happen.

Answer

m.akbari picture m.akbari · May 29, 2018
@Effect() public authenticate$ = this.actions$.pipe(
    ofType(authenticationActions.AUTHENTICATE),
     map(action => action.payload),
    exhaustMap((auth: any) => 
      this.authenticationService.authenticate(auth)
        .map((data: TokenData) => {
            return user: User = {
                token: data.token,
                username: 'dummy',
            };
        }).catch(error => { console.log(error); return Observable.throw(error); 
       }).pipe(
          map(user =>new authenticationActions.AuthenticateSuccessAction(user))
        )
    );)

  @Effect({ dispatch: false })
   loginSuccess$ = this.actions$.pipe(
     ofType(authenticationActions.AuthenticateSuccessAction),
     tap(() => this.router.navigate(['/']))
   );

Use exhaustMap and when you dispatching 'AuthenticateSuccessAction' action, do another effect for redirecting.

Personally, I like to separate all the services from effects, then you can use catchError() operator after success login for dispatching another action in case of failure login.

hope this works. PS: I did not verify this answer but logic is like this.