user4676340
user4676340

Reputation:

NgRx : store module creating several instances

I am encountering an issue with my code, using ngRx. Since the project is huge and it is more of a design question, I'm sorry I'm not providing a minimal and reproducting example.

I have a project with this structure :

AppModule
    PrimaryOutletModule
        SidenavComponent
        HeaderComponent

ExploitationComponentsModule [lazy loaded in AppRouting]
    MapComponent
    MaService

ServicesModule [imported in AppModule]
    HttpServicesModule
        ExploitationServicesModule
            ExploitationService

In this structure, I add this module to AppModule :

@NgModule({
  imports: [
    StoreModule.forRoot(exploitationReducers),
  ]
})
export class ExploitationStoreModule { }

Without any issue, all of my code works well. But when I add it to PrimaryOutletModule, ExploitationComponentsModule, and ExploitationServicesModule, and remove it from AppModule it stops working.

I want to remove it from the AppModule to avoid creating globally accessible stores (I want to give them meaningful scopes)

My first thought is to log the select and dispatch events, and when I do so, I see that events aren't caught. After adding this to the module :

constructor() { console.log('Store module instance created'); }

I see two instances. Following this SOF question, I realize that I have to use the forRoot method of the StoreModule.

But since my ExploitationStoreModule is already using it, I look for a solution and stumble upon this SOF question, saying that lazy loaded modules are creating new instances of modules.

If I understood it correctly, I am using forRoot twice, resulting in two instances of my ExploitationStoreModule.

Since I want to give correct scopes to my modules and don't let them access stores they don't have business with (for instance, ExploitationModule should not have access to SupervisionStore), I would like to not be forced to import all of my Store modules into my AppModule.

That brings the question : how should one declare stores in an application so that they aren't global and only provided in their respective modules ?

Upvotes: 0

Views: 785

Answers (1)

timdeschryver
timdeschryver

Reputation: 15505

You can use storeModule.forFeature in the feature modules. But the state will become available to your whole application when the module is being loaded.

Some extra resources:

A store holds the whole state tree of your application, and the following the best practices you should only have one store (there are edge cases where performance might be an issue where you would need multiple stores, I linked to the redux docs which have a great explanation).

If you import your store into your component with eg Store<FooState>, typescript only knows about the FooState but in fact your store holds your whole application's state, eg also BarState.

But personally I don't need to access the store inside my components because I'm using selectors, which doesn't really need the store type. For example this.store.select(selectEmployees).

Upvotes: 1

Related Questions