Adding NGRX
Add the store, effects and store-devtools
NGRX Store contains the basic NGRX features like reducers, selectors, actions, and the store.
Reducers are pure functions meaning asynchronous actions cannot be implemented in them, to do that we need effects.
NGRX Effects allows for asynchronous actions by capitalizing on the RXJS library.
In order to be able to debug our application, we also have to add @ngrx/store-devtools
ng add @ngrx/store
ng add @ngrx/effects
ng add @ngrx/store-devtools
What has changed?
package.json will be updated to contain the three packages
"packages": {
"": {
"name": "product-app",
"version": "0.0.0",
"dependencies": {
"@angular/animations": "^14.0.0",
"@angular/common": "^14.0.0",
"@angular/compiler": "^14.0.0",
"@angular/core": "^14.0.0",
"@angular/forms": "^14.0.0",
"@angular/platform-browser": "^14.0.0",
"@angular/platform-browser-dynamic": "^14.0.0",
"@angular/router": "^14.0.0",
"@ngrx/effects": "^14.0.2",
"@ngrx/store": "^14.0.2",
"@ngrx/store-devtools": "^14.0.2",
"json-server": "^0.17.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
...
}
In app.module.ts
We now have StoreModule in the ngModule import and its import statement from @ngrx/store,
and StoreDevtoolsModule is also imported and added to the imports array.
We also have EffectsModule too.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { ProductsListComponent } from './products-list/products-list.component';
import { ProductDetailComponent } from './product-detail/product-detail.component';
import { ReactiveFormsModule } from '@angular/forms';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from '../environments/environment';
@NgModule({
declarations: [AppComponent, ProductsListComponent, ProductDetailComponent],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
StoreModule.forRoot({}, {}),
EffectsModule.forRoot([]),
ReactiveFormsModule,
StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: environment.production }),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
If you check the NGRX documentation you'd see them using the StoreModule.forRoot method, but we will be using a different approach which I will explain.
A store is a big object and it can get messy if not properly organized. One way of organizing is to use slices. So we use StoreModule.forFeature to set a Feature Slice, also it is a cleaner approach.
@NgModule({...
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
StoreModule.forRoot({}, {}),
StoreModule.forFeature('app', appReducer), //We will create and import appReducer later
EffectsModule.forRoot([AppEffects]), // We will create and import AppEffects later
ReactiveFormsModule,
StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: environment.production }),
],
...})6
