Search code examples
angularrxjsngxs

NgXs @selector doesn't support async functions


Inside my NGXS store I have the following async selector

@Selector()
static async mainState(store: IMyStore): Promise<IMyState> {
    return this.getActiveState(store);
}

If I now subscribe to this selector

@Select(MyStore.mainState) state$: Observable<IMyState>;

If I subscribe to this stream I receive promises not IMyState objects. So I have to do:

this.state$.subscribe(p => {
    p.then(state => { ... });
});

I can cast the promise into a rxjs stream but then I receive streams

this.state$.subscribe(s => {
    s.subscribe(state => { ... });
});

So my question is, is there a way to support async selectors in ngxs?


Solution

  • The @Selector is used to "slice a specific portion of the state from the global state container" (not to call async function within it as I know).

    You can achieve what you're trying to do, like the following:

    • Create a new @Action to handle the async process.
    • Add a new property to your state to hold the mainState value.
    • After getting the result from async function, update the mainState with the proper value.
    • Create a new @Selector function to return the mainState.
    • Dispatch the created action within your component.
    • Add @Select property within your component to get the mainState from your state.

    Your code could look like the following:

    mystore.state.ts

    @Selector()
    static mainState(state: IMyStore): IMyState {
        return state.mainState;
    }
    
    @Action(LoadMainState)
    async loadMainState(ctx: StateContext<IMyStore>) {
      const _activeState = await this.getActiveState(store);
      ctx.patchState({ mainState: _activeState });
    }
    

    example.component.ts

    @Select(MyStore.mainState) state$: Observable<IMyState>;
    
    ngOnInit(): void {
      this.store.dispatch(new LoadMainState());
    }