Hi, I noticed that there is no documentation about dispatching multiple actions in an Effect. I had to deal with that in my code and I found many related questions on StackOverflow.
It's possible by using the switchMap or mergeMap operator returning an array of actions.
What are your thoughts about providing explanation and example on documentation about this ?
[x] Yes (Assistance is provided if you need help submitting a pull request)
[ ] No
It is possible, and there are multiple ways to do it, depending if you want to dispatch the effect right away, or wait until the service call is complete.
When you want to dispatch one right away:
@Effect
obs$: Observable<Action> = this.actions$.pipe(
ofType(action),
// notice that an array is returned
concatMap(() => [
of(new Action1(...)), // dispatched immediately
service.call().pipe(map() => new SuccessAction(), catchError(() => of(new ErrorAction))),
]),
// flattening an array of Observables
mergeMap(action => action),
)
When you want to dispatch on success:
concatMap(() =>
// not an array any more
service.call().pipe(map() => [new Action1(...), new SuccessAction()], catchError(() => of(new ErrorAction))),
),
// flattening a possible array of Observables
mergeMap(action => action),
When you want to dispatch when service call is done, regardless if it's Error or Success:
concatMap(() => forkJoin(
of(new Action1(...)),
service.call().pipe(map() => new SuccessAction(), catchError(() => of(new ErrorAction))),
]),
// flattening an array of Observables
mergeMap(action => action),
just replace this: mergeMap(action => action) by mergeAll() call. it looks neater :)
Does it seems legit to you to provide documentation about this ? There is nothing mentioning those tricks in Effect documentation.
It could a good entry for _recipe_ section :)
Dispatching multiple actions is considered an anti-pattern, so I'm obligated to show you this video 😉 https://www.youtube.com/watch?v=JmnsEvoy-gY
Oh snap. Busted, you're right.
Yeah, I've seen that video a number of times and shared that link even more time :)
But I've also seen code like
obs$: Observable<Action> = this.actions$.pipe(
ofType(action),
tap(() => this.store.dispatch(new BlahAction())),
concatMap(() => ...),
Not sure what's worse 🤷♂️
Also, if there is a chain of actions sometimes it's unavoidable to have the need to dispatch multiple.
But I'd have to agree that it's probably not the best practice.
At first I wasn't comfortable adding complexity in my Effects but then I saw many examples doing this trick, even blog article. The video is quite interesting maybe we can add a pitfall section to the documentation to prevent users from doing this ?
In the video you shared Mike discouraged this because it bring useless complexity into our app. Well I'm agree but in my case I had to deal with backend complexity without possibility to refactor this piece easily. How could I design actions without being constrained by my backend ?
As with most things, this is a guideline you should follow and there are use cases for doing it, but in general it shouldn't be considered standard practice.
Thanks for pointing this, I close the issue since it's not a good practice.
Most helpful comment
It is possible, and there are multiple ways to do it, depending if you want to dispatch the effect right away, or wait until the service call is complete.
When you want to dispatch one right away:
When you want to dispatch on success:
When you want to dispatch when service call is done, regardless if it's Error or Success: