1
votes

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 {
}
1
Is there an error in one of the JSON.parse that doesn't throw but ends execution of the task? - Derek Kite
no actually, I also logged details - Teoman Tıngır
That is strange. If you change the order of the dispatches, does anything change? - Derek Kite
nope, still it doesn't dispatch the same action - Teoman Tıngır
But if you wrap it in a setTimeout it works, so it isn't an error of spelling or wrong class. If you put console.log(action) in a reducer, any reducer does it log out the action? - Derek Kite

1 Answers

1
votes

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.