Search code examples
angularngrxangular-routerngrx-effects

Angular router navigation inside NgRx effect


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.


Solution

  • @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.