2

I'm learning NGXS with the Emitters plugin in Angular, and I have some trouble understanding how to declare my state files in a managable way.

I've had success declaring a simple .state file like this:


export type PageStatusCases = 'LOADING' | 'IDLE' | 'ERROR' | 'INITIALIZING';

export interface AppStateModel {
  pageStatus: PageStatusCases;
}

@State<AppStateModel>({
  name:     'AppState',
  defaults: {
    pageStatus: 'INITIALIZING'
  }
})
export class AppState {

  @Selector()
  static pageStatus(state: AppStateModel): PageStatusCases {
    return state.pageStatus;
  }

  @Receiver({type: '[Global] Page status'})
  static setPageStatus({patchState}: StateContext<AppStateModel>, {payload}: EmitterAction<PageStatusCases>): void {
    patchState({pageStatus: payload});
  }

}

Now I am trying a more complex example converting my Service in a State

In my service I have a lot of BehaviorSubjects keeping track of my UI's state.

  title: BehaviorSubject<string> = new BehaviorSubject('');

  backClick$: EventEmitter<void> = new EventEmitter<void>();
  primaryClick$: EventEmitter<void> = new EventEmitter<void>();

  toolbarVisible$: BehaviorSubject<boolean> = new BehaviorSubject(true);
  primaryVisible$: BehaviorSubject<boolean> = new BehaviorSubject(false);
  primaryDisabled$: BehaviorSubject<boolean> = new BehaviorSubject(false);
  primaryAutoDisabled$: BehaviorSubject<boolean> = new BehaviorSubject(false);
  primaryIcon$: BehaviorSubject<ToolbarPrimaryIcon> = new BehaviorSubject(ToolbarPrimaryIcon.ADD);

I've started to convert my BehaviorSubjects to parts of the state, but I realized that I need to create a lot of boilerplate code.

For every BehaviorSubject I need to:

  • Declare it in the state's model Interface
  • Declare it's default state in the State
  • Declare it's @Selector in the state "manifest"
  • Declare it's @Receiver (Action) in the state
  • Declare it's @Select in every component that needs it
  • Declare it's @Emitter in every component that needs it, for when I want to update it

My current situation is 100+ lines of code for correctly state-managing only 7 variables, so I think I am missing something. I'm not even complaining about the amount of visual noise added.

Clearly something is wrong

I would like to know what am I missing and what would be a better way of declaring state in a situation like this.

I am using NGXS with the emitters plugin because I through it was going to reduce the amount of boilerplate but I am not gaining much at the moment.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • I think this is a good question until we reached the bottom last two paragraphs where it reads like "best practices" question. It needs to be updated so that you're asking for help about a specific problem. Questions about best practices are off topic here. – Reactgular Apr 11 '19 at 14:45
  • I think that my code is wrong so I am asking for help from someone more expert than me – Polyterative Apr 11 '19 at 15:03
  • There is a lot of boilerplate code in state management. There is way more boilerplate if you use Redux. Ngxs is actually very compact compared to Redux. Based upon what I see in the question. I would say you're not doing anything *wrong*. – Reactgular Apr 11 '19 at 15:48

1 Answers1

3

There will be some boiler plate, but I think the main problem you might be seeing is having created a bunch of @Selector that are just accessing a single state property - the components that subscribe to the state changes don't need @Selector for this.

They can just subscribe to the state directly via a @Select binding Observable or just through a store.select() statement if need be. Also the image shows a bunch of @Select declarations with the state (also not needed).

I haven't used the Emitters stuff from NGXS Labs myself so I can't comment on that usage.

Garth Mason
  • 7,611
  • 3
  • 30
  • 39