0
votes

I'm starting out with NgRx and trying to get a very simple scenario up and running.

The problem:

I have a very simple service that is for now just returning a hard coded string value that I want to display on the UI by dispatching a CREATE action. Upon success the CREATE_SUCCESS action should be triggered, but the CREATE_SUCCESS action is never triggered

I expose 3 actions

export const CREATE =                 '[Profile] Create';
export const CREATE_SUCCESS =         '[Profile] Create Success';
export const CREATE_FAIL =            '[Profile] Create Fail';

export class CreateAction implements Action {
    readonly type = CREATE;

    constructor() { }
}

export class CreateSuccessAction implements Action {
    readonly type = CREATE_SUCCESS;

    constructor(public payload: any) { }
}

export class CreateFailAction implements Action {
    readonly type = CREATE_FAIL;

    constructor(public payload: any) { }
}

In the reducer I have the following

export interface State {
    loading: boolean;
    result: Observable<string>;
}

export const initialState: State = {
    loading: false,
    result: Observable.of('Default')
};

export function reducer(state = initialState, action: profile.Actions):State{
    switch (action.type) {
        case profile.CREATE: {
            return {
                ...state,
                loading: true
            };
        }

        case profile.CREATE_SUCCESS: {
            return {
                ...state,
                result: action.payload,
                loading: false
            };
        }

        case profile.CREATE_FAIL: {
            return {
                ...state,
                loading: false,
            };
        }

        default: {
            return state;
        }
    }
}

In the effect I have the following

Please note: I moved the catch clause into the switchMap method as suggested in many other threads

@Injectable()
export class ProfileEffects {
    @Effect() create$ = this._actions$
   .ofType(profile.CREATE)
   .switchMap(payload => this._profileService.create$()
       .map(res => ({ type: profile.CREATE_SUCCESS, payload: res }))
       .catch(e => Observable.of({ type: profile.CREATE_FAIL, payload: e })));

  constructor(
      private _profileService: ProfileService,
      private _actions$: Actions
  ) { }
}

In my component I dispatch the CreateAction

created$: Observable<string>;

 constructor
 (
     private _store: Store<any>,
     public navCtrl: NavController
 ) {
      this.created$ = this._store.select(s => s.profile.result.value);
 }

create_profile(){
    this._store.dispatch(new CreateAction());
}

and on the UI I have

<div>{{ created$ | async }}</div>

In the dev tools it is evident that on the CREATE action was dispatched, but no CREATE_SUCCESS action

enter image description here

There is no error messages displayed within the console.

1
Maybe the Effect is not recognizing profile.CREATE - try .ofType('[Profile] Create')Richard Matsen
I don't see export type Actions = CreateAction | CreateSuccessAction | CreateFailAction on your Actions code. Do you have that in your code?Richard Matsen
Yes, I just didn't include it in this thread, but I have it in my codeAndre Lombaard
So the only logical conclusion I can see is that this._profileService.create$() is not producing a value. Have you done any debugging in the switchMap to test it?Richard Matsen
Make sure you import EffectsModule.forRoot([ProfileEffects]), in your modulePrasad Parab

1 Answers

0
votes

Try making the following change:

.switchMap(payload => this._profileService.create$())
.map(res => ({ type: profile.CREATE_SUCCESS, payload: res })

By moving the parantheses, it calls map on the action itself, and not on the result of create$. This will map the CREATE into a CREATE_SUCCESS