Why you should consider using classes to declare the state of @ngrx/store

Michael De Abreu - Mar 3 '18 - - Dev Community

Hi there! Long time no see. I'm been kind of busy setting my blog, I'm sorry. I made the UI from the ground, because I didn't like any of the themes, as a fact, I don't like mine either, but we have to start somewhere. Anyway, here is the post, hope you enjoy it.


originally posted on my blog


Introduction

This week I've been playing around (again) with @ngrx, its store, effects, and go on, trying to integrating to a version of Tour of Heroes. It's been more than a year since the last time I play with it, and I have to say, I'm becoming a more productive developer, and this has also evolve to become a better platform. The fact that observables now use piped operators, makes everything easier to understand.

I been watching some tutorials, and been reading a lot about the changes introduced with recent versions of the store, and I don't know. I change the application state in two days. You may think that is a lot of time, but I didn't know how to use effects, and also I wanted to follow the Angular Style Guide on this one, and the example app of @ngrx does not follow it, and most of the redux examples are made, well, for a React project.

I had my thoughts about the structure of an Angular application, but they were heavily influenced by the structure of React applications. The current Angular Code Style have change my mind about, but this is for another post.

The recommended way

What I want to talk in this post, is about the recommended way to declare a state.

export interface AppState {
    counter: number;
}

export const initialAppState: AppState {
    counter: 3,
}
Enter fullscreen mode Exit fullscreen mode

Why? Ok, here is why. It IS recommended that you use a POJO for declaring the state, and the actions. But, does it really hurt to declare an immutable Typescript class to declare the State?

Classy

export class AppState {
    public readonly counter: number = 3;
}
Enter fullscreen mode Exit fullscreen mode

When this is set in the store configuration, the state initializes as a POJO as well, so there is no side effects going around here.

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

export class AppState {
    public readonly counter: number = 3;
}

const reducers = (state = new AppState(), action) => state; // Best reducer ever!


@NgModule({
  imports: [
    StoreModule.forRoot(reducers, {
      initialState: new AppState(),
    })
  ]
})
export class AppStoreModule {}
Enter fullscreen mode Exit fullscreen mode

I think this is clearer. You make sure that you set all the required properties, and only need to call the constructor when ever you need. And, you can use the AppState as a interface, wherever you want.

For AOT

If you would like to use this pattern with Angular AOT, you need to use the spread operator to introduce the new state, cause Angular Compiler needs to analyze all the metadata from the decorators. And you need to use function reducers, instead of a arrow function assignment.

function reducers(state = new AppState(), action) {
 return state; // Still the best reducer ever!
}

@NgModule({
  imports: [
    StoreModule.forRoot(reducers, {
      initialState: { ...new AppState() },
    })
  ]
})
export class AppStoreModule {}
Enter fullscreen mode Exit fullscreen mode

Do you think this is a good thing o a bad thing? Why? I would like to read your comments.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .