'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 1:[1]
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 theasync
process. - Add a new property to your state to hold the
mainState
value. - After getting the result from
async
function, update themainState
with the proper value. - Create a new
@Selector
function to return themainState
. - Dispatch the created
action
within your component. - Add
@Select
property within your component to get themainState
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());
}
Solution 2:[2]
Or if you still don't want to create an awkward piece of store you can flatten with switchAll(). Doing so you avoid ugly subscribe inside subscribe.
@Select(MyStore.mainState) stateHigherOrder$: Observable<Observable<IMyState>>;
state$!:Observable<IMyState>;
ngOnInit(): void {
this.state$ = this.stateHigherOrder$.pipe(switchAll());
}
And now this.state$ is what you wanted
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Amer |
Solution 2 | Gauthier Peel |