Skip to content

Aquent | DEV6

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages

Angular State Management with ngrx/store

Written by: Tunji Akinbami

ngrx/store is a great library for keeping our data organized in Angular applications. As our application grows it’s easy to lose track of what our application knows at a given point. It becomes critical that we cultivate an effective means of managing our application state, which has led developers to integrate state management frameworks into their applications.

Application state can exist in different ways. A good scenario is form data. Imagine that the requirement is to disable a navigation menu item unless all required fields of a form are filled. We might also have to deal with other issues like validation to notify us that the form is filled correctly. Now imagine after submitting the form, we have to wait for a backend response over a REST API or Websocket connection to enable the menu item. It’s very easy for these application states to get more complex and harder to manage as our application grows larger.

Redux is perhaps the most popular state management library used frequently in the React community. Redux rests on 3 basic principles:

  • Single source of truth: We have one place where all our data lives
  • State is read-only: No mutation; there is only one way to change state and that is through an action
  • Changes are made with pure functions: A new state is produced by taking the old state, applying the change, and producing the new state; the old state is never changed.

In addition, Redux applications are made up of 3 fundamental building blocks:

Actions: Actions are JavaScript objects that represent an event in our applications. They have payloads of information  that our application sends to our store. They are the only source of information for our store. Here is an example of an action:

   type: ‘CREATE POST’,
   payload: {
     body: ‘Write a new Angular post’

Reducers: Reducers are functions responsible for updating the state of our applications in response to the actions sent to the store. They are simple functions that take the current state and an action as arguments then return the next state.


Store: The store is a single object where the application state resides. Each application must have only one store and it has a few main roles which are:

  • Hold application state
  • Provide a way to access state
  • Provide a way to specify updates to state after actions have been dispatched
  • Registers and unregisters listeners using the subscribe(listener) function.

Enter ngrx/store

ngrx/store is a library used to manage state in Angular applications. It respects the same principles of Redux and is also built on top of rxjs

Let’s look at how we can use ngrx/store in a simple To Do application.

First off we’ll create a new Angular application with angular-cli from the command line:

ng new ngrx-lists

Next let’s add ngrx/store as a dependency with npm:

npm install @ngrx/store

Within the app folder, let’s create the following directories

  • models: for the list items
  • actions
  • reducers
  • create and read: to store the Angular components. You can use the command ‘ng generate component <component-name>’ to create the components.

Also let’s add another file called app.state.ts.

Let’s create a new file item.model.ts in the model directory where we will describe the item data:

export interface Item {
  name: string;

In the actions directory, let’s create a new file called todo.actions.ts. For this app we will only be performing one action ‘ADD_ITEM’ to add an item to the to do list.

import {Action} from '@ngrx/store';
import {Item} from '../models/item.model';

export const ADD_ITEM = '[TODO] Add';

export class AddItem implements Action {
  readonly type = ADD_ITEM;

  constructor(public payload: Item) {}

export type Actions = AddItem;

In the reducers directory, let’s create a new file todo.reducer.ts and add the following code:

import {Item} from '../models/item.model';
import * as TodoActions from '../actions/todo.actions';

const initialState: Item = {
  name: 'Learn ngRx'

export function reducer{state: Item[] = [initialState], action: TodoActions.Actions) {
   switch (action.type) {
     case TodoActions.ADD_ITEM:
        return[...state, actions.payload];
        return state;

First we create an initial state which is the first item in our to do list. In the reducer function we perform specific actions in addition to the action type. In this case, the ADD_ITEM action adds a newly entered item to the list.

Let’s define the app state in the app.state.ts file:

import {Item} from './models/item.model';

export interface AppState {
   readonly item: Item[];

We will import this file in the components where we need to access ngrx/store.

We need a way to add items from the UI. We’ve created a create component already so we’ll go ahead and add this to the create.component.ts file:

import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from './../app.state';
import { Item } from '../models/item.model';
import * as TodoActions from './../actions/todo.actions';
import { Observable } from 'rxjs';

  selector: 'app-create'
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
export class CreateComponent implements OnInit {

   constructor(private store: Store<AppState>) {}

   addTutorial(name, $event) { TodoActions.AddItem({name: name}));

   ngOnInit() {


Notice here we import Store from the ngrx/store library and use the dispatch function to dispatch an action. This the only we way can trigger a state change.

In the create.component.html file let’s design the mark up to add an item to the list:

<div class="left">

   <input type="text" placeholder="Name" #name onfocus="this.value=''">

   <button (click)="addTutorial(name.value, $event)">Add an Item</button>

In the read.component.ts file, let’s add the following code to enable us read the items we’ve added to the list. If you notice we’re accessing the items from the store using‘item’). We’re selecting the item property from app.module.ts in StoreModule.forRoot({}) where it is defined.

import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs';
import { Store } from '@ngrx/store';
import { Item } from '../models/item.model';
import { AppState } from './../app.state';
import * as TodoActions from '../actions/todo.actions';

   selector: 'app-read',
   templateURL: './read.component.html',
   styleUrls: ['./read.component.css']
export class ReadComponent implements OnInit {

   items: Observable<Item[]>;

   constructor(private store: Store<AppState>) {
     this.items ='item');
   ngOnInit() {


In read.component.html we’ll create the mark up to display the list of items:

<div class="right" *ngIf="items">
     <li *ngFor="let item of items | async">

This is the code for app.module.ts.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import {reducer} from './reducers/todo.reducers';
import { ReadComponent } from './read/read.component;
import { CreateComponent } from './create/create.component';

  declarations: [
  imports: [
       item: reducer
  providers: [],
  bootstraps: [AppComponent]
export class AppModule { }

Finally let’s add the read and create components to the app.component.html file, and also add some styling.



body, html {
  margin: 0;
  padding: 0;
  font-family: 'Arial';

.left, .right {
  width: calc(50% - 6em);
  padding: 3em;

input[type="text"] {
  width: 100%;
  padding: 5px;
  margin-bottom: 10px;
}/* You can add global styles to this file, and also import other style files */

When you run ng serve from the command line, you should see something similar to the UI below:

UI after running ng serve

Nice! You’ve just created an app using Angular and ngrx/store! You can access the source code at this git repository.

While ngrx is a great tool for managing state in our Angular applications, it should be noted that it could be overkill for small-sized applications. I suggest using it for large-scale applications where there are lots of state changes. For further reading, you can check out the official documentation here

Want to learn more Angular?

Sign up for Angular training course

View Course Details