Skip to main content

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:

  1. 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.
  2. 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.
  3. 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.