Search code examples
angularreduxrxjsngrxngrx-effects

Action dispatch the second time doesn't effect in RxJS and Angular 6


I have an @Effect that manage the login. The steps are the following:

  • Call the service
  • Save the token (into the class);
  • Select a the application Store to see if the user asked another page (before the redirect into login. Because maybe he wanted to go in 'profile' page, but then I redirected him into Login, saving the wanted page 'profile'). In this case a redirect the user
  • Do other actions (set the variable 'isAuthenticated', save the token, decode the token, in the Store).

All works. This is the code of auth.effects.ts:

@Injectable()
export class AuthEffects {
    constructor(private store: Store<fromApp.AppState>, private actions$: Actions, private router: Router, private authService: AuthService, private route: ActivatedRoute, private toastr: ToastrService) {
    }
    tokenObj: { token: string };
    @Effect()
    authLogin$ = this.actions$
        .ofType(AuthActions.DO_LOGIN)
        .pipe(map((action: AuthActions.DoLogin) => {
            return action.payload;
        })
            , switchMap((authData: { email: string, password: string }) => {
                return from(this.authService.login(authData.email, authData.password));
            })
            , map(tokenObj => this.tokenObj = tokenObj) 
            , withLatestFrom(this.store.select(('core')))
            , take(1)
            , map(([action, storeState]) => {
                if (storeState.redirectUrl) {
                    this.router.navigate([storeState.redirectUrl]);
                } else {
                    this.router.navigate(['/']);
                }
            })
            , mergeMap(() => {
                return [
                    {
                        type: AuthActions.LOGIN 
                    },
                    {
                        type: AuthActions.SET_TOKEN,
                        payload: this.tokenObj.token
                    },
                    {
                        type: ProfileActions.DECODE_TOKEN,
                        payload: this.tokenObj.token
                    },
                    {
                        type: CoreActions.REMOVE_REDIRECT_URL
                    }
                ];
            })
            , catchError((err, caught) => {
                this.toastr.error(err.message);
                // Quindi, alla fine, torniamo l'Observable di errore, affinché si possa ri-provare l'operazione
                return caught;
            })
        );
}

This is the function inside the login.component.ts:

 onLogin(form: NgForm) {
    const email = form.value.email;
    const password = form.value.password;
    this.store.dispatch(new AuthActions.DoLogin({ email: email, password: password }));
  }

This is the function that triggers logout in header.component.ts:

onLogout() {
    this.store.dispatch(new AuthActions.Logout());
    this.store.dispatch(new ProfileActions.CancelLoggedUser());
    this.router.navigate(['/login']);
}

The issue is: If I logout, I type again the email and the password, I press login and nothing happens. In particular, opening Ngrx DevTools I see that the DO_LOGIN is dispatched (with property values of the form) but the server is not called. Event if I put a breakpoint inside the effect, it doesn't trigger. Why?

This is a screen of all the actions: Login ---> home ---> logout ---> do second time login: enter image description here


Solution

  • The issues cames from the take(1) that unsubscribes the effects observable.

    An ngrx effect is a singleton, once unsubscribed will never subscribe again.