Angular router navigation inside NgRx effect
There should be an approach allowing not to create separate effect for redirect, something like
this.actions$.pipe(
ofType(authenticationActions.AUTHENTICATE),
switchMap(action =>
this.authenticationService.authenticate(action.payload).pipe(
map(data => new authenticationActions.successAction(data)),
tap(() => this.router.navigate(['/'])),
catchError(error => new authenticationActions.failAction(error))
)
);
The thing is that tap
will not be invoked if the service call failed, both map
and tap
will be skipped in favor of catchError
if the failure case.
following the response of m.akbari, in the case they use the actions differently, the "dispatch : false" goes to the last.
the key is the "dispatch : false", if this is not indicated an infinite loop is generated
loginNavigate$ = createEffect(
() => this.actions$.pipe(
ofType(usuariosActions.loginUsuarioSuccess),
tap(() => {
console.log('iniciando la navegacion');
this.router.navigate(['/']);
})
), { dispatch: false }
);
@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.