# 18. Create selectors

## 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 `createFeatureSelector`functions @ngrx/store keeps track of the latest arguments in which your selector function was invoked. Because selectors are [pure functions](https://en.wikipedia.org/wiki/Pure_function), 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](https://en.wikipedia.org/wiki/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.

{% code title="src/app/state/spinner/spinner.selectors.ts" %}

```typescript
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
);

```

{% endcode %}

## 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.&#x20;

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

{% code title="src/app/event/container/event/event.component.ts" %}

```typescript

---------- 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 ----------
```

{% endcode %}

## StackBlitz Link

{% embed url="<https://stackblitz.com/github/duncanhunter/angular-and-ngrx-demo-app/tree/18-create-selectors>" %}
Web Link: Link to the demo app running in StackBlitz
{% endembed %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://duncanhunter.gitbook.io/angular-and-ngrx/18.-create-selectors.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
