NgRx

What's NgRx?

NgRx is a group of libraries “inspired” by the Redux Pattern which in turn is “inspired” by the Flux Pattern.

Redux Pattern is a simplified version of the Flux Pattern and NgRx is an Angular/RxJS version of the Redux Pattern.

Redux

Three fundamental principles of Redux...

  1. Single Source of Truth.

  2. Immutable State.

  3. Pure Functions.

Actions

  • Action reports that something happened. Nothing more!

  • Actions do not describe, how the state has to be changed.

  • Actions can also carry an (optional) payload.

import { Action } from '@ngrx/store'
export const CONTACT_SEARCH = '[Contact] Search';
export const CONTACT_CREATE = '[Contact] Create';
export class ContactSearchAction
implements Action {
type = CONTACT_SEARCH
constructor(public payload: SearchCriteria) {}
}
export class ContactCreateAction implements Action {
type = CONTACT_CREATE
constructor(public payload: Contact) {}
}
export type ContactActions = ContactSearchAction | ContactCreateAction;

Reducers

  • These reducers are the only structure that is allowed to alter the state.

  • All state changes are implemented inside of reducers.

  • It takes the current state and the action as parameters.

import {
ContactState, initeContactState, contactAdapter
} from '../state/contact.state';
import {
ContactActions, CONTACT_SEARCH_SUCCESS
} from '../actions/contact.actions';
export function contactReducer(
state: ContactState = initeContactState,
action: ContactActions): ContactState {
switch (action.type) {
case CONTACT_SEARCH_SUCCESS: {
return contactAdapter.addAll(action.payload, state);
}
default: {
return state;
}
}
}

App State

  • App State is Ready Only.

  • The only way to change the state is to emit an action, an object describing what happened.

export interface AppState {
contacts: Contacts[];
}
export const initialAppState: AppState = {
contacts: []
};

Entity Adapter

  • Provide reducer functions to maintain collections of entities.

  • Provide implementation for adding, deleting, or updating entities.

  • Provide commonly used selected for the entities.

import {
createEntityAdapter, EntityAdapter, EntityState
} from '@ngrx/entity';
export interface ContactState extends EntityState<Contact> {}
export const contactAdapter: EntityAdapter<Contact> = createEntityAdapter<Contact>({});
export const initialContactState: ContactState = eReferralMessageAdapter.getInitialState({});
const {
selectIds, selectEntities, selectAll, selectTotal
} = eReferralMessageAdapter.getSelectors();

Selectors

Selectors are simple pure functions, that allows to slice and get only the part of the application state that relevant for the scenario.

import { createSelector } from '@ngrx/store';
import { AppState } from '../state/app.state';
import { contactAdapter } from '../state/contact.state';
export const selectCurrentContact = (state: AppState)
=> state.currentContact;
const selectContacts = (state: AppState)
=> state.contacts;
const cotactSelectors = contactAdapter.getSelectors();
export const selectAllContacts = createSelector(
selectContacts,
cotactSelectors.selectAll
);