Reputation:
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
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