NgRx Effects loaded twice
Asked Answered
M

5

9

I have a simple feature module, which provides services and imports its own stats fragment as a feature:

@NgModule({
  imports: [
    CommonModule,
    StoreModule.forFeature('alarms', alarmsReducer, { initialState: alarmsInitialState }),
    EffectsModule.forFeature([AlarmsEffects])
  ],
  declarations: [],
  providers: [
    AlarmsFacade,
    AlarmsService
  ]
})
export class AlarmsModule {
}

And I'm importing this module in two other modules, a page that needs to have access to the services, and AppModule as I need to import it here in order to have the state initialized properly.

When I'm checking Redux DevTools, I can clearly see that @ngrx/store/update-reducers is called twice for the feature alarms. This results in the state being frozen, stoping all the effects (including the ones not related to alarms feature).

The timeline below can show the issue (a third @ngrx/store/update-reducers action is fired after the effects init while there's only two features at the moment, it contains reducers for feature 'alarms'):

Redux DevTools timeline

How can I avoid the effects to be loaded twice? I tried to remove the module from AppModule but it's breaking the alarms state as there's no default one provided for my selectors.

Margaretmargareta answered 7/9, 2018 at 9:3 Comment(1)
Would need a repro in order to solve this.Heins
M
15

Here were my issues:

After upgrading to ngrx 8, I didn't remove the @Effect() decorators from the effects I've transitioned to createEffect.

I removed {dispatch: false} from the effects (now using createEffect) instead of placing them as the second argument, after the arrow function.

Also see: Effect gets called twice when using StoreDevtoolsModule.instrument()

Mon answered 21/10, 2019 at 18:33 Comment(1)
Removing @Effect when using createEffect solved my effects running twice.Nanji
A
0

If you need some slice of the state in multiple modules then its obviously not a feature state but the main state. So move that slice into your main module and implement reducers/effects for it there.

Ambie answered 7/9, 2018 at 9:16 Comment(1)
But then, the issue is that I'll have to put a lot of slices in the app module, which is why I originally want to split things into modules, to be easier to read and avoid a massive imports array in my app module.Margaretmargareta
S
0

I'm quite late to the party, but in my case it was two actions sharing the same action type.

For example:

export const rejectItem = createAction('Reject Item', props<{item: Item}>)
export const rejectItemSuccess = createAction('Reject Item');

This caused the effect for the first rejectItem action to be invoked twice.

The fix was just to use a unique action type

export const rejectItem = createAction('Reject Item', props<{item: Item}>)
export const rejectItemSuccess = createAction('Reject Item Success');
Sectorial answered 21/8, 2023 at 7:27 Comment(0)
M
-1

You'll also get effects firing twice if you subscribe to the effect observable itself, like by composing effects out of other effects (rather than the actions they dispatch).

You can solve it by subscribing to the actions the effects dispatch, or you can also use shareReplay() or other similar "hot" observable solution.

Mair answered 18/2, 2020 at 18:2 Comment(0)
E
-2

If you are using angular 6 you can do the provideInRoot feature.

@Injectable({
    providedIn: 'root'
})
export class MyEffects {
Eric answered 7/9, 2018 at 9:25 Comment(1)
Unfortunately this doesn't fix this issue :/Margaretmargareta

© 2022 - 2025 — McMap. All rights reserved.