2
votes

After switching some feature Effects over to the new createEffct() pattern, all of the service requests they call are now firing twice in my console output.

Here's the action:

export const getSetting = createAction(
  '[Practitioner Settings] Get Setting',
  props<{ name: string }>(),
);

Here's an example of one such Effect using the old syntax:

@Effect()
getSetting$: Observable<Action> = this.actions.pipe(
  ofType(PractitionerSettingsActionTypes.GetSetting),
  map((action: PractitionerSettingsActions.GetSetting) => action.name),
  switchMap((name: string) => {
    return this.practitionerSetingsService
               .getSetting(name)
               .pipe(
                 map(response => new PractitionerSettingsActions.GetSettingSuccess(response)),
               )
    }),
  );

and the new syntax, based on examples at: https://github.com/ngrx/platform/blob/master/projects/example-app/src/app/books/effects/collection.effects.ts:

@Effect()
getSetting = createEffect(() =>
  this.actions.pipe(
    ofType(PractitionerSettingsActions.getSetting),
    mergeMap(({ name }) => {
      return this.practitionerSetingsService
                 .getSetting(name)
                 .pipe(
                    map(response => PractitionerSettingsActions.getSettingSuccess({ setting: response })),
                  )
      }),
    )
  );

I suspect it's the mergeMap operator that's causing this behavior since it's the only difference between the two, but I'm not sure why it would cause this, or how to access the action's payload in another way.

I have made no other changes to my application other than update the Ngrx Actions, Reducers and Effects to the v8 patterns that would cause the service calls to be executed twice.

What operator should I be using to access the action payload if not mergeMap? and if mergeMap is correct, why are my effects running more than once?

1
As a test can you add this.actions.subscribe((action) => console.log(action)) somewhere? That way you can narrow down if your actions are firing off multiple times. switchMap only allows one inner subscription to be active at a time. It cancels any active inner subscription as soon as a new one comes in. mergeMap does not have this same cancelling effect. Every inner subscription will run. learnrxjs.io/operators/transformation/mergemap.html learnrxjs.io/operators/transformation/switchmap.html - Noremac
Let me give that a try - Brandon
I added a log statement to each of my service methods. Changing mergeMap to switchMap yields the same result. I still see my log statement twice in the console for each method called by an Effect. - Brandon
Just to verify, I switched to my develop branch, ran the code with the old pattern and I only see one log statement per service method. - Brandon

1 Answers

4
votes

If you check the example you've linked the @Effect() annotation is absent, and it is present in the question code. I think that is the reason it works in that way for you