What is the difference between StoreModule.forRoot() and StoreModule.forFeature()

Recently ngrx store changed the way to register the store variables in an angular application.

What is the difference between StoreModule.forRoot() and StoreModule.forFeature()

Do we need to register both to make the application work?


Solution 1:

Its used with lazy loaded reducers. When you have (lazy loaded) feature modules and you want to register reducers within that module, then you use forFeature. Otherwise, in your AppModule you use forRoot.

Solution 2:

Always Import forRoot() calls I think this is probably pretty obvious, but just for the record, you’ll need to make sure you’ve already imported the root store and effects module in your main application.

imports: [
    StoreModule.forRoot({}),
    EffectsModule.forRoot([]),
    ...

If you have reducers or effects that apply at this level, you should add them in here, but even if you don’t have any reducers or effects at the root level of your application, you need to make these two calls. Otherwise, the forFeature() calls won’t be able to access the root store or effect location to add in the reducers and effects for the feature.

Solution 3:

First of all, for dealing easily with Angular modules, you've to know some basic terminology that will help you with problems similar to this in the future.

An Angular app is (basically) made of a module, named "AppModule" that is conventionally known as Root Module: this is the main module of the application, the one bootstrapped in the main.ts file that is, actually, the application entry point. When you import some external modules into the imports array of the AppModule, you usually invoke the static method forRoot for giving an initial configuration to that module: it's the case of the StoreModule's forRoot method, which you set the store's initial configuration.

You can develop your application finding some "zone of concerns" to solve a specific part of your problem. When you merge components, directives, services and other Angular elements into a module, that module becomes a feature module because, as the naming convention suggests, it provides a feature to your application. Doesn't matter how you load a module (Eagerly or Lazily), it will always be a feature module.

Now, maybe, you've already answered to your question by yourself:

  1. The forRoot method is invoked in the AppModule and, generally, once in the application to initialize the Store and provide the initial reducers/actions/state configuration. If you use the EffectsModule, you'll invoke the forRoot method on this module too:

    @ngModule({ imports: [ StoreModule.forRoot(), EffectsModule.forRoot() ] }) class AppModule {}

  2. The forFeature method is invoked in any feature module that requires it's own part of the state management: as an example, an UserModule will define it's own portion of the state, describing the required actions, reducers and so on. If you use the EffectsModule, remember to invoke the forFeature method against it too. As you may have understood by yourself, forFeature (as the more generic Angular's forChild method) can be invoked multiple times for the same imported module in the application:

    AppModule -> StoreModule.forRoot(...) UsersModule -> StoreModule.forFeature(...) OtherModule -> StoreModule.forFeature(...)

Finally, remember that the forRoot and the forFeature signatures are slightly different from each other: the latter has, in fact, the first parameter that describes the feature name. The other parameters, if I can recall properly, are the same as the forRoot method. If you try generating a boilerplate for a feature module with the @ngrx/schematics package with the following command:

ng generate feature user/User -m modules/users/users.module.ts --group

You will find that the feature name will simply be the lowercased version of the User word in the given command: user.