NGRX - from the beginning, part III, NGRX Store
Tags: ngrx, angular, tutorial, webdev
Published: 2019-04-06 06:14:16

Follow me on [Twitter](https://twitter.com/chris_noring), happy to take your suggestions on topics or improvements /Chris

> NGRX is an implementation of the pattern Redux. It's made for the framework Angular and adds Typescript and reactiveness with RxJS

This article is part of a series:

- [NGRX — from the beginning](https://dev.to/azure/ngrx-from-the-beginning-7k7), part I, Pub-sub,
- [NGRX — from the beginning, part II](https://dev.to/azure/ngrx-from-the-beginning-part-ii-redux-4006), part II Redux
- NGRX — from the beginning, part III, NGRX store, **we are here**
- NGRX — from the beginning, part IV, NGRX store, improving our code
- NGRX — from the beginning, part V, NGRX effects, _in progress_
- NGRX — from the beginning, part VI, NGRX entity, _in progress_

If you come into this part with no idea what Redux or Pub-Sub is, I urge you to read part I and part II first. We won't explain things like Reducer or Action or how we *dispatch* messages cause that would make this article too long.

In this article, we will cover

- **Set up and install**, we will explain how to scaffold a project and also install the necessary dependencies and we will also add our first state property and Reducer function  
- **Displaying data**, here we will cover how to inject the Store service and how to display data from the Store in our markup
- **Change state**, after we've shown how to show the data we will here focus on how to change the data or as it is referred to with Redux, to dispatch an action

## Set up and install
Ok, we need to do the following:

1. Scaffolding an Angular project
2. Install @ngrx/store
3. Set up @ngrx/store

### Install
Ok, first things first, let's create ourselves an Angular project by typing the following in the terminal:

```
ng new NameOfMyProject
cd NameOfMyProject
```

Thereafter we remain in the terminal and enter:

```
npm install @ngrx/store
```
This install our library and we are ready to configure our project to `@ngrx/store`.

### Set up
Ok, we have a project let's set it up. There are two things we need to do:

1. Import the `StoreModule`
2. call `StoreModule.forRoot()` and provide it with an object consisting of a number of  state, reducer pairs

Ok, we open up `app.module.ts` and enter:

```ts
import { StoreModule } from '@ngrx/store';
```

Lets call `StoreModule.forRoot()` next. As mentioned above we need to give it an object consists of a number of state, reducer pairs, like so:

```ts
{
  state: stateReducer, 
  secondState: secondStateReducer
  ...
}
```

Ok, we understand the overall shape so let's show in real code what this might look like:

```ts
const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    default:
      return state;
  }
}
```

Next, in the same file `app.module.ts`, we need to add our `StoreModule` to our list of `imports`, like so:

```ts
imports: [
  BrowserModule,
  AppRoutingModule,
  StoreModule.forRoot({
    counter: counterReducer
  })
]
```
As you can see we are now providing an object to `StoreModule.forRoot()` containing our `counter`, `counterReducer` pair.

## Displaying data
Ok, that covers the bare minimum set up we need to make @ngrx/store work. However we can't show our data at this point. To show data we need to inject the `Store` service into a constructor of the component that aim to display data. Let's go into `app.component.ts` and add the needed import:

```ts
import { Store } from '@ngrx/store';
```
And the needed injection into the component class constructor:

```ts
constructor(private store: Store<any>) {}
```
At this point you might wonder about the use of `any` as template argument to the `Store`, let's leave that for now and work on improving it in just a little bit.

### Selecting data
Ok, the `Store` service will let us select data from its inner state if we use the method `pipe()` and the operator `select()`, like so:

```ts
import { Store, select } from '@ngrx/store';

@Component({
  ...
})
export class AppComponent {
  counter$;

  constructor(private store: Store<any>) {
    this.counter$ = this.store.pipe(
      select('counter')
    )
  }
}
```
We are importing the `select()` operator from `@ngrx/store` and we also assign the result of our `pipe()` invocation to a variable `counter$`. `counter$` is an Observable and that means we can use an `async` pipe to show the content. Let's now head to our `app.component.html` file and type the following:

```html
My counter: {{ counter$ | async }}
```
Save an run your project and your browser should now display `My counter: 0`

### With a function selector
So far everything works, but let's go back to how we inject our `Store` service in the `AppComponent` constructor. We gave it the template argument `any`. We can definitely improve that, but how? The idea is to feed it an interface that represents your Store state. Currently, your Stores state looks like this:

```ts
{
  counter
}
```
So let's create an interface that corresponds to this, namely:

```
// app-state.ts
export interface AppState {
  counter: number;
}
```
Above we are declaring the only `existing` state property `counter` and we declare what type it is as well. Ok, next step is to use `AppState` for our Stores template, so let's update `app.component.ts`. 
First add this import:

```ts
import { AppState } from './app-state';
```

Let's now replace `any` with `AppState`:

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

We can do more though, we can leverage this by switching from the `select()` method that takes a string to the one that takes a function, like so:

So this:

```ts
this.counter$ = this.store.pipe(
    select('counter')
  )
```

Becomes:

```ts
  this.counter$ = this.store.pipe(
    select(state => state.counter)
  )
```
What's so great about this you ask? Well now we get help from the compiler if we attempt to select a property from the state doesn't exist, only `state.counter` would be a valid choice. Also if our state is nested this is the only way we would be able to reach a state like `state.products.data` for example, if we had a state `products` that is.

## Change state
Ok, great, we can display a state property from our store, what about changing it? For that, we have a `dispatch()` method that will allow us to send a message to the Store. The message is in the form of an Action object. Ok, let's build out our UI a bit. Go into `app.component.html` and add the following:

```
// app.component.html

<button (click)="increment()">Increment</button>
```
Now, head to `app.component.ts` and add the method `increment()`, like so:

```ts
@Component({})
export class AppComponent {
  increment() {
    // add dispatch call here
  }
}
```
Ok, we need to do the following to send a message to the store:
- Construct an action object with the message type `INCREMENT`
- Call `dispatch()` on the Store service instance

Ok, to construct an object we can use an object literal, like so:

```
const action = { type: 'INCREMENT' };
```

The reason for using the message INCREMENT lies in how we constructed the `counterReducer` function, let's look at at it quickly:

```ts
const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    default:
      return state;
  }
}
```

It's clear it expects a message that has a property `type` and for that message type value to be `INCREMENT`. Ok, looks good, lets make the call to `dispatch()`:

```ts
@Component({})
export class AppComponent {
  // constructor omitted for brevity
  increment() {
    const action = { type: 'INCREMENT' };
    this.store.dispatch(action);
  }
}
```
Invoking `increment()` will now lead to our message being sent to the store and for the `counterReducer()` to be invoked and for our `counter` value to be updated by one. Try it yourself.

## Summary
That's all we planned to cover in this part. We've shown how to install `@ngrx/store` but also how to set up a state, reducer pair in our `StoreModule.forRoot()`. Furthermore, we've shown how you can select data from the `Store` service and also how to update data by using the mentioned `Store` service and its `dispatch()` method. In the next part we will look at a more rich example and look at how we can improve things using enums and built in interfaces, so stay tuned :)