18. Create selectors

In this section we will create selectors in NgRx which are a cornerstone piece of getting your NgRx architecture right.

1. Add selector file for spinner state

Selectors are methods used for obtaining slices of store state. @ngrx/store provides a few helper functions for optimising this selection. Selectors are a big deal to help get your architecture right and you can read more in the docs here https://github.com/ngrx/platform/blob/master/docs/store/selectors.md.

When using the createSelector and createFeatureSelectorfunctions @ngrx/store keeps track of the latest arguments in which your selector function was invoked. Because selectors are pure functions, the last result can be returned when the arguments match without re-invoking your selector function. This can provide performance benefits, particularly with selectors that perform expensive computation. This practice is known as memoization.

  • Make a spinner.selectors.ts file.

  • Make a getSpinnerState using createFeatureSelector, we can do this for other different feature state making it possible to join state slices together.

  • Make a getSpinner selector using the createSelector method to return just the boolean value of the isOn property.

src/app/state/spinner/spinner.selectors.ts
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { State } from './spinner.reducer';

export const getSpinnerState = createFeatureSelector<State>('spinner');

export const getSpinner = createSelector(
  getSpinnerState,
  (state: State) => state.isOn
);

2. Use the new selector in our EventComponent

It is possible to see in this step how selectors clean our u=our code and make it easier for other developer son our team to know what they can get from the store.

  • Use the getSpinner selector versus our inline function where we "dot" into the property on the state tree we want.

src/app/event/container/event/event.component.ts

---------- ABBREVIATED CODE SNIPPET ----------

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Store, select } from '@ngrx/store';

import { Attendee } from '../../../models';
import { EventService } from '../../services/event.service';
import { State } from '../../../state/state';
import { StartSpinner, StopSpinner } from '../../../state/spinner/spinner.actions';
import { getSpinner } from '../../../state/spinner/spinner.selectors';

@Component({
  selector: 'app-event',
  templateUrl: './event.component.html',
  styleUrls: ['./event.component.scss']
})
export class EventComponent implements OnInit {
  spinner$: Observable<boolean>;
  attendees$: Observable<Attendee[]>;

  constructor(
    private store: Store<State>,
    private eventService: EventService
  ) {}

  ngOnInit() {
    this.getAttendees();
    this.spinner$ = this.store.pipe(select(getSpinner));
  }

---------- ABBREVIATED CODE SNIPPET ----------

Last updated