I have a CoreModule
which is eagerly loaded and contains the main app state, and a ContractHolder.module
which uses NgxsModule.forFeature([ContractHolderState])
to declare a new state to be added to the main one when it is loaded. However, the components in the lazy-loaded module see an initial state of {}
(so not initialized as defined in ContractHolderState
), and later this state is updated when ContractHolderState
's @Action
handlers update the state.
In the rest of the app, I see the app state containing the initialized ContractHolderState
but it is not updated when ContractHolderState
updates it!
So in short, my lazy-loaded module does not see the app state at all, but instead sees an empty object which is updated by the lazy state ContractHolderState
, while the rest of the application sees the initial value defined for ContractHolderState
but it is never updated.
Code:
Core.module
, which defines the main app state and is imported by App.module
:
const ngxsStates = [ConfigurationState, AuthenticationAuthorizationState];
@NgModule({
imports: [
NgxsStoragePluginModule.forRoot({
key: appStateNames.authorization,
}),
NgxsModule.forRoot(ngxsStates, { developmentMode: !environment.production }), // <--- NGXS states
NgxsReduxDevtoolsPluginModule.forRoot(),
NgxPermissionsModule.forRoot(),
],
providers: [...],
exports: [...],
declarations: [...],
})
export class CoreModule {}
I have ContractHolder.module
which is lazy-loaded:
@NgModule({
declarations: [MainViewComponent],
imports: [
CommonModule,
CoreModule, // <--- imports core module with the main state
RouterModule.forChild([{
path: '',
component: MainViewComponent,
}]),
NgxsModule.forFeature([ContractHolderState]) // <--- declares state
],
})
export class ContractHolderModule { }
Here's the ContractHolderState
:
@State<ContractHolderStateModel>({
name: appStateNames.contractHolders,
defaults: {
contractHolders: [],
},
})
export class ContractHolderState {
@Selector()
static contractHolders(state: ContractHolderStateModel): IContractHolder[] {
return state.contractHolders;
}
}
This is how ContractHolder.module
is lazily loaded by the routing definition in app-routing.module
:
const routes: Routes = [
{
path: 'home-page',
component: PageComponent,
children: [
{
path: 'ch',
outlet: 'page',
loadChildren:
(): Promise<ContractHolderModule> => import('./contract-holder/contract-holder.module')
.then(m => m.ContractHolderModule) // <--- lazy-loaded ContractHolder.module
},
]
},
{
path: '**',
component: LoginComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Now the main-view.component
used in the contract holder module looks at the state via @Select(ContractHolderState.contractHolders) allCh$: Observable<IContractHolder[]>;
. I also tried looking at this.store.snapshot()
which returned an empty object. After ContractHolderState
updated the state it is no longer an empty object, but the rest of the state (from the rest of the app) is never there.
While this is happening, the main app sees the full state but the ContractHolderState
always has its default value of {contractHolders: []}
and it is never updated.
The problem was with importing CoreModule
which defines the main state more than once. We had multiple modules importing core module. I kept the core module imported by the App module and all other functionality is now in a new SharedModule.