NgRx
NgRx is a framework for managing state in Angular applications. It's an implementation of Redux, a state management pattern made famous by React, but built specifically for Angular.
NgRx Basics
At its core, NgRx is about managing state - data that needs to be shared across components. It uses three main principles:
- Single source of truth: NgRx maintains a single, read-only state tree in your application. This makes it easier to track changes over time and debug or inspect the application.
- State is read-only: The only way to change the state is by dispatching actions. An action describes what happened, but does not contain any code to update the state.
- Changes are made using pure functions: To specify how the state tree is transformed by actions, you write pure reducers.
Installing NgRx
To install NgRx, you need to use the Angular CLI and add the NgRx schematics to your project. Here's how you can do it:
ng add @ngrx/store
Setting up the Store
After installing NgRx, the next step is setting up your store. The store is where your state will live. Here is an example of how to set up a store for a simple counter application:
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './counter.reducer';
@NgModule({
imports: [
StoreModule.forRoot({ count: counterReducer })
],
})
export class AppModule { }
Actions
Actions are dispatched from your application and interpreted by the reducer to create a new state. They are plain objects that have a type
property, and optionally a payload
property.
Here's an example of how you can define actions for the counter application:
export enum CounterActionTypes {
Increment = '[Counter] Increment',
Decrement = '[Counter] Decrement',
Reset = '[Counter] Reset',
}
export class Increment implements Action {
readonly type = CounterActionTypes.Increment;
}
export class Decrement implements Action {
readonly type = CounterActionTypes.Decrement;
}
export class Reset implements Action {
readonly type = CounterActionTypes.Reset;
constructor(public payload: number) {}
}
Reducers
Reducers in NgRx are responsible for handling transitions from one state to the next state in your application. Reducer functions handle these transitions by determining which actions to handle based on the type.
Here's an example of a reducer for the counter application:
export function counterReducer(state = 0, action: Action) {
switch (action.type) {
case CounterActionTypes.Increment:
return state + 1;
case CounterActionTypes.Decrement:
return state - 1;
case CounterActionTypes.Reset:
return 0;
default:
return state;
}
}
Selectors
Selectors are pure functions used to select, derive and compose pieces of state. They can be used in components to get data from the store.
Here's how you can use a selector to get the current count from the store:
import { createSelector } from '@ngrx/store';
export const selectCount = (state) => state.count;
In your component, you would use the store.select
method to select the count:
this.count$ = this.store.select(selectCount);
Conclusion
NgRx is a powerful tool for managing state in Angular applications. It might seem complex at first, but once you understand the basic principles, it can greatly simplify your application architecture and make your code easier to understand and debug.