Getting started with NgRx

At some point while building our Angular applications we feel the need to have a state management mechanism. One of the most popular state mechanism for Angular applications is NgRx which is inspired by Redux.

To understand how to work with NgRx, I built a tiny ToDo app and then tried to use NgRx with it. Initially my ToDo app just consisted of the following:

  1. AddToDoComponent
  2. DisplayToDoComponent
  3. ToDoService

The responsibilities of the above parts of the application were very simple and clear:

AddToDoComponent - Responsible for adding a ToDo item. DisplayToDoComponent - Responsible for displaying a ToDo items. ToDoService - Responsible for sharing data between AddToDo and DisplayToDoComponent

The flow was pretty simple:

ToDoService exposed a todos$ subject to AddToComponent and DisplayToDoComponent:

 export class ToDoService {
   public toDos$: Subject<ToDo> = new Subject<ToDo>();
 }

So, AddToDoComponent was simply emitting each ToDo entered by the user with the below simple line of code:

this.toDoService.toDo$.next(new ToDo(this.item));

… and the DisplayComponent, simply subscribed to the toDo$ subject, pushed it into an array and displayed it on the template with help of *ngFor directive. This is simple and probably doesn’t even need a state management mechanism, but it would be fun to see how to achieve the same behavior using NgRx.

So let’s start. There are few key concepts in NgRx, let’s take them one by one:

I believe we are now one with our set up. We have defined actions and reducers, registered our store. Now, let’s dispatch AddToDoItem action from our AddToDoComponent:

export class AddToDoComponent {
  item: string;

  constructor(private toDoService: ToDoService, private store: Store<{ toDos: { toDos: ToDo[] } }>) {
  }

  onSubmit() {
    const toDo = new ToDo(this.item);
    this.store.dispatch(new ToDoActions.AddToDoItem(toDo));
    this.item = '';
  }
}

We have dispatched an action, reducer function will modify our state according to the dispatched action. Now, what is left?

So, the last thing that is left is DisplayToDoComponent accessing this updated state:

export class DisplayToDoComponent implements OnInit {
  constructor(private store: Store<{toDos: {toDos: ToDo[]}}>) { }
  toDosState: Observable<{toDos: ToDo[]}>;

  ngOnInit() {
    this.toDosState = this.store.select('toDos');
  }
}

… and we can then display ToDo items in our template:

<ul>
    <li *ngFor="let toDo of (toDosState | async).toDos">
        
    </li>
</ul>

That’s it! But before we end I would like us to take a deeper look at the statement:

this.toDosState = this.store.select('toDos');

The above statement introduces us to another very important concept i.e Selectors. Selectors like reducers are pure functions. They take state as an argument and return data which can be passed to the Components. We used store.state method to get ToDo items from the Store by passing state toDos.

Follow Me

Github

Twitter

LinkedIn

More Blogs By Me