NGRX vs NGXS: State Management Techniques

Knoldus Blog Audio
Reading Time: 3 minutes

Before starting, let’s first understand what NGRX and NGXS are and we will see NGRX vs NGXS? Both NGRX and NGXS are state management libraries for an Angular application and they both share the Redux principle. 

NGRX: NGRX is one of the libraries which helps to manage the state of the application. It is a Redux execution for Angular. If you want to know about NGRX, you can visit here.
NGXS: NGXS is a state management pattern + library for Angular. It acts as a single source of truth for your application’s state, that is providing simple rules for predictable state mutations. If you want to know more about NGXS, you can visit here.

Now, let’s start comparing these two state management techniques as both are good in their way, but there are still some differences between them that make them unique. Nowadays, most angular developers are comfortable with NGXS, as it is much easier to understand and code. 

In addition, the key differences are: 

  1. State mutations
  2. Handling side-effects
  3. Use of decorators

Let’s compare it regarding the code: 

Actions in NGXS  vs Actions in NGRX

mother.action.ts in NGXS: 

export class FeedChild {
 static readonly type = '[Mother] Feed Child';
 constructor(public name: string, public price: number) {}
}

mother.action.ts in NGRX:

import { Action } from '@ngrx/store';
export const FEED_CHILD = '[Mother] Feed Child';
export class FeedChild extends Action {
 readonly type = FEED_CHILD;;
 constructor(public payload: { name: string, price: number }) {}
}
export type Actions = FeedChild;

State in NGXS vs Reducer, Effect, Selector in NGRX

mother.state.ts in NGXS:

import { State, Selector, Action, StateContext } from '@ngxs/store';
import { MotherService } from '../services/mother.service';
export interface MotherStateModel {
 childName: string;
 childFeed: boolean;
}
@State<MotherStateModel>({
 name: 'mother',
 default: {
   childName: null,
   childFeed: false
 }
})
export class MotherState {
 constructor(private motherService: motherService) {}
 @Selector()
 static childName(state: MotherStateModel) {
   return state.childName;
 }
 @Selector()
 static childFeed(state: MotherStateModel) {
   return state.childFeed;
 }
 @Action(FeedChild)
 feedChild(ctx: StateContext<MotherStateModel>, action: FeedChild) {
   return this.motherService.feedChild(action.childName, action.price).pipe(
     tap(() => ctx.setState({ childName: action.childName, childFeed: true }))
   );
 }
}

mother.reducer.ts in NGRX:

import { createFeatureSelector, createSelector } from '@ngrx/store';
import * as fromActions from '../actions/mother.actions';
export interface State {
 childName: string;
 childFeed: boolean;
}
export const initialState: State = {
 childName: null,
 childFeed: false
};
export function reducer(state: State = initialState,  action: fromActions.Actions): State {
 switch(action.type) {
   case fromActions.FEED_CHILD:
     return {
       childName: action.price.name,
       childFeed: true
     };
 }
 return state;
}
export const getMotherState = createFeatureSelector<State>('mother');
export const getMotherName = createSelector(getMotherState, state => state.childName);
export const getMotherFeed = createSelector(getMotherState, state => state.childFeed);

mother.effects.ts in NGRX:

import { Injectable } from '@angular/core';
import { Actions, Effect } from '@ngrx/effects';
import { Action } from '@ngrx/store';
import { Observable } from 'rxjs';
import { MotherService } from '../services/mother.service';
import * as fromActions from '../actions/mother.actions';
@Injectable()
export class MotherEffects {
 constructor(
   private actions$: Actions,
   private motherService: MotherService
 ) {}
 @Effect()
 feedChild$: Observable<Action> = this.actions$
   .ofType<fromActions.FeedChild>(fromActions.FEED_CHILD)
   .pipe(
     map((action: fromActions.FeedChild) => action.payload),
     switchMap(payload => this.motherService.feedChild(payload.childName, payload.price))
   );
}

Components in NGXS vs Components in NGRX:  

mother.component.ts in NGXS:

import { Select, Store } from '@ngxs/store';
import { MotherState } from '../mother.state';
import { FeedChild } from '../mother.actions';
import { Observable } from 'rxjs';
@Component({ ... })
export class MotherComponent {
 @Select(MotherState.childName)childName$: Observable<string>;
 @Select(MotherState.childFeed)childFeed$: Observable<boolean>;
 constructor(private store: Store) {}
 feedChild(name, price) {
   this.store.dispatch(new FeedChild(name, price));
 }
}

mother.component.ts in NGRX:

import { Store } from '@ngrx/store';
import { MotherState } from '../mother.state';
import { FeedChild } from '../mother.actions';
import * as fromChild from '../mother.reducer';
import { Observable } from 'rxjs';
@Component({ ... })
export class MotherComponent {
 childName$: Observable<string>;
 childFeed$: Observable<boolean>;
 constructor(private store: Store<fromMother.State>) {
    this.childName$ = this.store.select(fromMother.getChildName);
    this.childFeed$ = this.store.select(fromMother.getChildFeed);
  }
  feedChild(name,price) {
       this.store.dispatch(new FeedChild({ name, price }));
    }
}

To sum up of all, it points that the basic difference between NGRX and NGXS are: 

NGRX vs NGXS
Conclusion:

In this blog, we have seen the difference between NGRX and NGXS. Both have the state management technique and are good in their way. But, as of now most of the developers work by using NGXS, as it is simple and easy to understand, and it reduces the boilerplate code that is; less complex.

knoldus-advt-sticker

Written by 

Alka Vats is a Software Consultant at Knoldus. She is passionate about web development. She is recognized as a good team player, a dedicated and responsible professional, and a technology enthusiast. She is a quick learner & curious to learn new technologies. Her hobbies include reading books, watching movies, and traveling.