'Ngxs - How do I chain actions?
I want to do something like this for my registration.
When clicking the register button, this will be executed:
this.store.dispatch(new Register(user))
.subscribe(response => {
localStorage.setItem('token', JSON.stringify(response.token));
let redirectUrl = this.store.dispatch(new RegisterSuccess(response));
if (redirectUrl) {
this.router.navigate([redirectUrl]);
} else {
this.router.navigate(['/home']);
}
}, error => {
this.store.dispatch(new RegisterFailed());
});
State:
@Action(Register)
register({ patchState }: StateContext<AuthenticationStateModel>, { payload }: Register) {
patchState({
isLoading: true
});
return this.authenticationService.register(payload);
}
@Action(RegisterFailed)
registerFailed({ patchState }: StateContext<AuthenticationStateModel>) {
patchState({
isLoading: false
});
}
@Action(RegisterSuccess)
registerSuccess(sc: StateContext<AuthenticationStateModel>, { payload }: RegisterSuccess) {
sc.patchState({
user: payload.user,
token: payload.token,
isAuthenticated: true,
isLoading: false,
});
return sc.getState().redirectUrl;
}
1) I want the Register action to return the Observable from http request.
2) Then subscribe to it, if the request is success, fire RegisterSuccess(which I want it to return an item from state). If the request is fail, fire RegisterFailed.
I've actually already done it by putting the same code in the state(with little modification ofc), but I feel like it's too messy and not the proper way so put it in the component instead but I can't make it work again.
Solution 1:[1]
This is how I am doing it:
- When user performs an action, just dispatch with action parameters (if any), for example
new MyAction()
. Generally, subscribing to this dispatched action is not required and I find that it makes the code looks messy too. - The
@Action
function process stuff and optionally dispatch success/failed actions (e.g.MyActionSuccess
,MyActionFailed
, or some other meaningful action). If there can be only one outcome for this action, then don't bother dispatching a success - completion of this action IS success. - To handle successful (etc...) execution of actions, I subscribe to action handlers for routing/redirection stuff. These would be subscribed/unsubscribed by the component based on the component's lifecycle. (e.g.
ngOnInit()
,ngOnDestroy()
).
To be honest, I do not know if this is the right or best way, just how I am doing it now.
Solution 2:[2]
The docs suggest you do the following:
For syncronous actions:
return ctx.dispatch(new TakeAnimalsOutside());
For asynchronous actions:
return this.animalService.feed(action.animalsToFeed).pipe(
mergeMap(() => ctx.dispatch(new TakeAnimalsOutside()))
The interesting this with dispatch
is that you can do
dispatch([new Action1(), new Action2(), ...etc])
Solution 3:[3]
you can use concatMap
it is rxjs
operator
example.pipe(
concatMap(() => this.store.dispatch(new FirstAction())),
concatMap(() => this.store.dispatch(new SecondAction())),
concatMap(() => this.selectorDependOnAction$)).subscribe((res) => {
//anything you want to do it
});
}
some resources for concatMap
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 | kctang |
Solution 2 | Erik Philips |
Solution 3 | Ahmed Korany |