Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dispatch multiple ngrx actions at the same time

I'm using ngrx and have a scenerio where I need to dispatch 2 actions at the same time. My state has properties for updating and updated and looks like below.

//from reducer
const defaultCardState: CardState = {
    ids: [],
    entities: {},
    loaded: false,
    loading: false,
    adding: false,
    added: false,
    updating: false,
    updated: false,
    deleting: false,
    deleted: false
};

These are the actions I'm dispatching from my component

this.store.dispatch(fromCard.updateCard({id: id1, changes: {name: name1}}))
this.store.dispatch(fromCard.updateCard({id: id2, changes: {name: name2}}))

Below are my action, reducer and effect

//Update Card Actions
export const updateCard = createAction('[Cards] Update Card', props<{id: string, changes: any}>())
export const updateCardSuccess = createAction('[Cards] Update Card Success', props<{changes: any}>());
export const updateCardFail = createAction('[Cards] Update Card Fail')

//Reducer
on(fromCards.updateCard, (state) => ({...state, updating: true, updated: false})),
    on(fromCards.updateCardSuccess, (state, action: any) => ({...cardAdapter.updateOne(action.changes, state), updated: true, updating: false})),
    on(fromCards.updateCardFail, (state, action: any) => fromCards.updateCardFail),

//Update Card Effect
updateCard$: Observable<Action> = createEffect(() => this.actions$.pipe(
    ofType(fromCardActions.updateCard),
    map((action: any) => { return {id: action.id, changes: action.changes}}),
    switchMap((action: any) => this.cardService.updateCard(action).pipe(
        map((res) => (fromCardActions.updateCardSuccess({changes: action }))),
        catchError(() => of(fromCardActions.updateCardFail))
    ))
))

What is the best way to dispatch these actions one after the other so the updating and updated fields don't conflict? If I run just one of these it works but if I dispatch them both together like shown above, only one completes. I see that both actions get dispatched but only one success action gets dispatched.

like image 382
mattc19 Avatar asked Oct 29 '25 17:10

mattc19


2 Answers

Similar to Tony's answer, but using the correct operator:

@Effect()
dispatchMultiAction$: Observable<Action> = this.actions$.pipe(
    ofType<SomeAction.Dispatch>(someActions.Dispatch),
    mergeMap(_ => [
            new someActions.InitData(),
            new someActions.GetData(),
            new someActions.LoadData()
        ])
    )
);
like image 167
xandermonkey Avatar answered Oct 31 '25 08:10

xandermonkey


You can dispatch multiple action in your effect and I would recommend you do that only in the effect

Consider example below

@Effect()
dispatchMultiAction$: Observable<Action> = this.actions$.pipe(
    ofType<SomeAction.Dispatch>(someActions.Dispatch),
    switchMap(_ =>
        of(
            new someActions.InitData(),
            new someActions.GetData(),
            new someActions.LoadData()
        )
    )
);
like image 35
Tony Ngo Avatar answered Oct 31 '25 07:10

Tony Ngo