Teoman Tıngır
Teoman Tıngır

Reputation: 2866

Ngrx - Reducer can't receive action

I'm trying to load some cached details when app initializing. I'm using builtin APP_INITIALIZER provider of angular.

In this provider I'm running the init method of the AppService and loading those cached information, dispatching some actions. 3 of 4 actions are gracefully dispatching but when I try to dispatch order details reducer doesn't get this action and I can't transfer order details to store.

But when I look at redux chrome extension I'm able to see my action that getting dispatch, but if I log incoming actions in reducer I can't see my action.

The weird part it is if I run loadCachedOrderDetails method after three seconds later with setTimeOut method, setCachedOrderDetails action dispatched successfully..

What is exactly happening ? How can I dispatch setCachedOrderDetails action properly ?

Here is full definition of the provider

    {
      provide: APP_INITIALIZER,
      useFactory: (app: AppService) => () => app.init(),
      deps: [AppService],
      multi: true
    }

AppService init method

  init() {
    const request = this.loadCachedRequest();
    if (request) {
      this.loadCurrentLocation(request);
    }
    this.loadCachedBasketItems();
    this.loadCachedOrderDetails();
  }

and the method


  loadCachedOrderDetails() {
    const details = JSON.parse(localStorage.getItem('orderDetails'));
    if (details) {
      this.store.dispatch(PanelActions.setCachedOrderDetails({details}));
    }
  }

and panel store where I register the reducer

@NgModule({
  imports: [
    StoreModule.forFeature(panelFeatureKey, fromPanel.reducer),
    EffectsModule.forFeature([PanelEffects]),
  ],
  exports: [
    StoreModule,
    EffectsModule
  ]
})
export class PanelStoreModule {
}

Upvotes: 3

Views: 1101

Answers (1)

satanTime
satanTime

Reputation: 13539

If you use EffectsModule.forFeature it means this module isn't main one and your app has been initialized already and your module was highly likely lazyloaded or initialized later once app is needed in it.

Therefore you can't rely on any INIT triggers. Because they can emit earlier than your feature has been set and is ready to listen to actions.

but you can simply use constructor of your module to dispatch required actions.

@NgModule({
  imports: [
    StoreModule.forFeature(panelFeatureKey, fromPanel.reducer),
    EffectsModule.forFeature([PanelEffects]),
  ],
  exports: [
    StoreModule,
    EffectsModule,
  ]
})
export class PanelStoreModule {
  constructor(app: AppService) {
    app.init();
  }
}

Or simply move the effect and the reducer to the forRoot part.

Upvotes: 2

Related Questions