Search code examples
angularngrxngrx-effects

Ngrx effect dispatch different actions - best practice


I am trying to dispatch different action based on type splitting up in several effects. I know i am doing something wrong or thinking in a wrong way, so I am sharing my concerns.

The use case is the following:

  • I have several actions which has to link to the same effect, as both actions, accepted and selected must be notified to the backend:
notifyChangeInBack$ = createEffect(
    () => {
      return this.actions$.pipe(
        ofType(
          InteractionActions.interactionAccepted,
          InteractionActions.interactionSelected,
        ),
        exhaustMap(action => {
          const { interaction } = action;
          return this.interactionDatasource.notifyInteractionChange(interaction)
            .pipe(
              map(() => InteractionActions.changeInteractionSuccess({ interaction })),
              catchError(() => of(InteractionActions.changeInteractionError({ interaction })))
            )
        })
      );
    }
  );
  • Sequentially, after dispatching changeInteractionSuccess action, there are different functionality to execute based on action type. If the action was interactionAccepted, the user has to navigate to a concrete page. If the action was interactionSelected the user has to navigate to a url based in a logic. Right now, I have two effects for doing this:
navigateToCustomer$ = createEffect(
    () => {
      return this.actions$.pipe(
        ofType(InteractionActions.interactionAccepted),
        tap((action) =>
          // logic for navigation...
        )
      );
    },
    { dispatch: false }
  );

navigateToLastInteractionState$ = createEffect(
    () => {
      return this.actions$.pipe(
        ofType(InteractionActions.interactionSelected),
        concatLatestFrom(() => this.interactionFacade.selectInteractionsUi$),
        tap(([action, interactionsUi]) => {
          // logic for navigation...
        })
      );
    },
    { dispatch: false }
  );

My question is: how can I connect changeInteractionSuccess action after notifying to back with different effects that needs the previous action? Should I create two different effects for notifying to back that listen to the actions separately? I.E: one effect for interactionAccepted action which do the request and return a proper action and the same for the interactionSelected action.

Many thanks in advance!!!


Solution

  • You can nest actions, this is a pattern to listen for action X, then wait until Y occurs. For example:

    navigateToCustomer$ = createEffect(
        () => {
          return this.actions$.pipe(
            ofType(InteractionActions.interactionAccepted),
            switchMap((action) => {
               return this.actions$.pipe(ofType(InteractionActions.changeInteractionSuccess))
            })
          );
        },
        { dispatch: false }
      );