Why I am unable to emit reducer function from an effect?

57 views Asked by At
  login$ = createEffect(() => {
    return this.action$.pipe(
      ofType(fromActions.loginStart),
      exhaustMap(action => {
        return this.authService
          .login({
            username: action.username,
            password: action.password,
          })
          .pipe(
            map(data => {
              const user = this.authService.handleLogin(data);
              return fromActions.loginSuccess({
                roles: user._roles,
                token: user._token,
                expiration: user._expiration.toString(),
              });
            }),
            catchError(error => {
              return of(fromActions.loginFailure({ error: error.message }));
            })
          );
      })
    );
  });

In the above code snippet the return to loginSuccess reducer works successfully, but same call to reducer loginSuccess doesn't works for below function:

  autoAuth$ = createEffect(() => {
    return this.action$.pipe(
      ofType(fromActions.autoAuthenticate),
      map(() => {
        const user = this.authService.getAuthDataFromLocalStorage();
        if (user && user._expiration && user._expiration > new Date()) {
          this.authService.onSuccessfulAuthentication(user._expiration);
          return fromActions.loginSuccess({
            roles: user._roles,
            token: user._token,
            expiration: user._expiration.toString(),
          });
        } else {
          return fromActions.loginFailure({ error: 'Login Failed' });
        }
      })
    );
  });

Function is being executed successfully, as there is one more effect which is successfully executed by both the snippets.

  loginRedirect$ = createEffect(
    () => {
      return this.action$.pipe(
        ofType(loginSuccess),
        map(() => {
          this.router.navigate(['home']);
        })
      );
    },
    { dispatch: false }
  );
}

I am unable to figure out why the reducer is not being called in the second case as action is dispatched in both cases.

Have tried replacing loginSuccess with a different action which does not require any data to be passed , but still the code not able to go to reducer

1

There are 1 answers

3
Razvan Fulea On

You should use switchMap instead of map to preserve the Observable result:

 autoAuth$ = createEffect(() => {
    return this.action$.pipe(
      ofType(fromActions.autoAuthenticate),
      switchMap(() => { // switchMap here
        const user = this.authService.getAuthDataFromLocalStorage();
        if (user && user._expiration && user._expiration > new Date()) {
          this.authService.onSuccessfulAuthentication(user._expiration);
          return of(fromActions.loginSuccess({
            roles: user._roles,
            token: user._token,
            expiration: user._expiration.toString(),
          }));
        } else {
          return of(fromActions.loginFailure({ error: 'Login Failed' }));
        }
      })
    );
  });