Multiple actions getting triggered ngrx8

The loginsuccess gets trigerred twice on dispatching the login action, the redux flow is working as expected i'm unable to trace why the login success gets trigerred twice. I have pasted the complete code structure and I need some help in fixing this, thanks.

auth.actions.ts
export class Login implements Action {
  readonly type = AuthActionTypes.Login;
  constructor(public payload: {login: ILogin}) {}
}

export class LoginSuccess implements Action {
  readonly type = AuthActionTypes.LoginSuccess;
  constructor(public payload: ILogin) {}
}

export class LoginFailure implements Action {
  readonly type = AuthActionTypes.LoginFailure;
  constructor(public payload: { err: any }) {}
}

auth.effects.ts

@Effect()
  logAdd = createEffect(() => this.actions.pipe(
    ofType(AuthActionTypes.Login),
    switchMap((action: any) =>
    this.authService.loginRequest(action.payload.login)
    .pipe(map((res: any) => new LoginSuccess(res)),
      catchError(err => of(new LoginFailure({err})))
    ))),{dispatch: false}
  )
}

auth.reducer.ts

export interface AuthState {
  login: ILogin
}

export interface AuthPartialState {
  readonly [AUTH_FEATURE_KEY]: AuthState;
}

export const initialState: AuthState = {
  login: null
};

export function authReducer(
  state: AuthState = initialState,
  action: AuthAction
): AuthState {
  switch (action.type) {
    case AuthActionTypes.LoginSuccess: {
      state = {
        ...state,
       login: action.payload
      };
      break;
    }
  }
  return state;
}

From login.component.ts

onSubmit(){
    this.store.dispatch(new loginRequest.Login({
      login: {
        username: this.login.value.username,
        password: this.login.value.password
      }
    }))
  }

I have attached the screenshot from redux devtools on how it is trigerred. Redux DevTools

As shown the picture, both login success comes up with username and password. I Updated effects according to ngrx 8 but still facing same issue.

2 answers

  • answered 2019-09-15 09:44 Tony Ngo

    I saw you mix up between ngrx v7 and v8 syntax, you should used one syntax only to avoid unexpected behavior. Maybe you will need to return like this

    @Effect()
      logAdd = createEffect(() => this.actions.pipe(
        ofType(AuthActionTypes.Login),
        switchMap((action: any) =>
        return this.authService.loginRequest(action.payload.login)
        .pipe(map((res: any) => new LoginSuccess(res)),
          catchError(err => of(new LoginFailure({err})))
        )))
      )
    }
    

    Example:

    getPosts$ = createEffect(() =>
        this.actions$.pipe(
          ofType(PostActions.LoadPosts),
          switchMap(_ => {
            return this.postService
              .getPosts()
              .pipe(
                map(
                  (posts: IPost[]) => PostActions.LoadPostsSuccess({ posts }),
                  catchError(errors => of(PostActions.LoadPostsFail(errors)))
                )
              );
          })
        )
      );
    

  • answered 2019-09-15 13:13 timdeschryver

    The effect is registered twice in your example, once with the @Effect() decorator and the second time with the createEffect factory function.

    If you remove the @Effect(), it will only dispatch once.

    You can make use of the ngrx linting rules I've been creating to prevent this - https://github.com/timdeschryver/ngrx-tslint-rules