What is NgRx?
NgRx is a framework for building reactive applications in Angular.
Why use NgRx or any statemanagement framework?
Communication between components is a key feature of a reactive frontend application. In Angular, components communicate with each other using events. This is done using the @Input
and @Output
decorator. Consider a chain of such props in a component, which will end up as an extraneous props. To resolve this we can maintain a store within the application and use it to maintain the state of all the components.
Install NGRX
Within the Angular project, run the following command to install NGRX:
1
|
npm install @ngrx/{effects,entity,router-store,store,store-devtools} --save
|
Once that is installed, now lets install ngrx-store-localstorage
to persist the state of the store in the browser.
1
|
npm install ngrx-store-freeze ngrx-store-localstorage --save
|
Create the store globally
src/app/store/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
export interface State {
root: AppState;
}
export const reducers: ActionReducerMap<State> = {
root: CoreReducer,
};
export const coreInitState: State = {
root: APP_STATE,
};
const reducerKeys = ["root"];
export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
return function (state, action) {
return reducer(state, action);
};
}
export function localStorageSyncReducer(
reducer: ActionReducer<any>
): ActionReducer<any> {
return localStorageSync({ keys: reducerKeys })(reducer);
}
export const metaReducers: MetaReducer<State>[] = !environment.production
? [debug, localStorageSyncReducer]
: [localStorageSyncReducer];
export const appState = (state: any): AppState => state.root;
|
Import the store
src/app/app.module.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
StoreModule.forRoot(reducers, { metaReducers }),
StoreDevtoolsModule.instrument({
maxAge: 25,
logOnly: environment.production,
}),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
|
Feature Store
Once we create a root store, we can extend the store for multiple feature within a feature module of the application.
For example, let us now consider having a feature module for User module.
We’ll need a action and reducer to begin with. Remember that the source in createActionGroup
and name in createFeature
should be same.
src/app/user/user.action.ts
1
2
3
4
5
6
7
|
export const flow = createActionGroup({
source: 'user',
events: {
'Create User': props<UserState>();
}
})
|
src/app/user/user.reducer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
interface UserState{
firstName: string | null,
lastName?: string | null,
age: number | null
}
const initialState: UserState {
firstName: null,
age: null
}
export const userFeature = createFeature({
name: 'user',
reducer: createReducer({
initialState,
on(UserActions.createUser, (state, payload) => ({...state, ...payload}))
})
})
|
Once done with the reducer we’ll have it imported in the UserModule
.
src/app/user/user.module.ts
1
2
3
4
5
6
7
8
9
10
11
|
@NgModule({
...
imports:[
...
StoreModule.forFeature(userFeature)
...
]
...
})
export class UserModule {}
|