9

I was wondering whether it's possible to abstract the @Selectors and/or the @Action handlers from the @State class to a separate file? As the state grows bigger and as the selectors more complex, I'd like to move them to a separate file to keep the state class cleaner. Is there any way to do that in NGXS?

Edit: for future reference, I got an answer on the NGXS slack channel and it is indeed possible. We can create a separate selector class where to store all our selectors, passing them the state of interest as an argument.

export class EntityStateSelectors {
  @Selector([EntityState])
  thing(state: EntityStateModel) {
    return state.thing;
  }
}

As of now I still haven't figured out how to do the same for the action handlers, but extracting the selectors to a separate file already cleaned up the state class a lot !

Ale
  • 103
  • 6
  • Perhaps you need to have more states and/or child states? – Rich Duncan Aug 27 '18 at 22:23
  • Thanks for the input but that's not what I meant - I have a complex app structure already, with multiple child states. I also have quite a lot of selectors and action handlers, and to keep a clean app structure I wanted to split them to separate files (as in ngrx, which is the pattern I'm coming from). And it's possible! Check my updated question. – Ale Aug 29 '18 at 09:07
  • How do you handle creating circular references among parent->child relationships in this case? – rivanov Nov 18 '18 at 22:01
  • @Ale I used the same pattern to separate selectors from action handlers but struggle to make it works with `angular9.1` + `ngxs3.6`. I have runtime errors at app init like `Cannot read property 'NGXS_SELECTOR_META' of undefined` where selector are used.. any hint on it? – bertrandg Jun 05 '20 at 09:25
  • @bertrandg Were you able to fix this `NGXS_SELECTOR_META`? I'm stuck with that error combining selectors of multiple states. – Carlos Esteban Lopez Jaramillo Aug 24 '20 at 17:02
  • @CarlosEstebanLopezJaramillo yes, a bit tricky but it works now, check this github issue i did: https://github.com/ngxs/store/issues/1631 – bertrandg Aug 25 '20 at 18:49
  • 1
    @bertrandg Thanks man, we already fixed it, had to refactor the data structure so the dependency was 1 way. – Carlos Esteban Lopez Jaramillo Aug 25 '20 at 22:30

1 Answers1

8

You can have a separate file for your selectors and is highly recommended. You can create a file like app.selectors.ts with something like this:

export class AppSelectors {

  @Selector([AppState])
  static viewModel(state: AppStateModel) {
    // your selector logic here
  }

}

Then you can use normally in your components like this:

@Component({...})
export class AppComponent {
  @Select(AppSelectors.viewModel) vm$: Observable<ViewModel>;
}

This greatly reduces the size of your app.state.ts file since it leaves just the action handlers there. Also, this makes your code easier to test since your selectors are just pure functions

  • 1
    Yep, if you see I updated my question a while back with pretty much what you suggested here :) – Ale Nov 11 '20 at 11:01