Search code examples
ngrxngrx-effectsngrx-reducers

ngrx twice reducer call during effect


I am developing using an angular app using ngrx. I have defined the convention below to implement a loading indicator:

  • Initially state of each entity is set to null
  • Make it an empty object on effect starts
  • Fill it with fetched data on effect done

Now one of my effects will be this:

  @Effect()
  LoginUser$ = this._actions$.pipe(
    ofType<LoginUser>(EUserActions.LoginUser),
    switchMap((params) => { new LoginUserSuccess(<IUser>{}); return of(params); }), // for loading indicator to be shown
    switchMap((params) => this._userService.loginUser(params.payload)),
    switchMap((currentUser: IUser) => of(new LoginUserSuccess(currentUser)))
  )

but the reducer call in the first switchMap does not get occur. What is the problem.


Solution

  • I have finally solved my problem some other way. I now am dispatching another action, inside the primary action to update the state. For example this is how I have done it:

    user.service.ts

    export class UserService {
      constructor(private _store: Store<IAppState>) { }
    
      loginUser(model): void {
        this._store.dispatch(new AddBusy(EUserActions.LoginUser));
        this._store.dispatch(new LoginUser(model));
      }
    
      getAllUsers(): void {
        this._store.dispatch(new AddBusy(EUserActions.GetAllUsers));
        this._store.dispatch(new GetAllUsers());
      }
    }
    

    user.actions.ts

    export class UserEffects {
    
      @Effect()
      LoginUser$ = this._actions$.pipe(
        ofType<LoginUser>(EUserActions.LoginUser),
        switchMap((params) => this._userLogic.loginUser(params.payload)),
        switchMap((currentUser: IUser) => { this._store.dispatch(new RemoveBusy(EUserActions.LoginUser)); return of(currentUser); }),
        switchMap((currentUser: IUser) => of(new LoginUserSuccess(currentUser)))
      )
    
      @Effect()
      getAllUsers$ = this._actions$.pipe(
        ofType<GetAllUsers>(EUserActions.GetAllUsers),
        switchMap(() => this._userLogic.getAllUsers()),
        switchMap((users: IUser[]) => { this._store.dispatch(new RemoveBusy(EUserActions.GetAllUsers)); return of(users); }),
        switchMap((users: IUser[]) => of(new GetAllUsersSuccess(users)))
      )
    
      constructor(
        private _userLogic: UserLogic,
        private _actions$: Actions,
        private _store: Store<IAppState>,
      ) { }
    }
    

    This solved my problem nice.