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.
@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.
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 }
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With