'NgRx how to dispatch 2 actions in order

I cant seem to find a way with the NgRx (not RxJS Style) to dispatch 2 Actions in an effect.

I would like to (IN THIS ORDER):

  1. delete a Movie in the Database with an effect,
  2. dispatch deleteMovieSuccess
  3. dispatch getMovies (I need to reload all Movies afterwards!)

I tried to do it like below, but it just fires the first Action, and I cannot see the other action: In my log I can see:

  • [Movie list] Delete movie
  • [Movie list] Get movies
  • [Movie list] Get movies successful

I have the folloing actions:

export const getMovies = createAction('[Movie List] Get Movies', props<{search: string, page: number, limit: number}>());
export const getMoviesSuccess = createAction('[Movies List] Get Movies Success', props<{ search: string, page: number, limit: number }>());

export const deleteMovie = createAction('[Movie List] Remove Movie', props<{ movieToDelete: Movie, search: string, page: number, limit: number }>());
export const deleteMovieSuccess = createAction('[Movie List] Remove Movie Success', props<{ movieToDelete: Movie }>());

and the following effect:

    deleteMovie$ = createEffect(() => this.actions$.pipe(
      ofType(MovieActions.deleteMovie),
      mergeMap(({movieToDelete, search, page, limit}) =>
        this.moviesService.deleteMovie(movieToDelete)
        .pipe(
          map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
          map(() => MovieActions.getMovies({search, page, limit})),
          catchError(() => EMPTY)
        )
      )
    )
  );

How can I trigger BOTH, deleteMoviesSuccess, and getMovies in this order?

I`ve also tried with switchMap and and faltMap, but never are both Actions dispatched correctly. I just cant seem to understand, how dispatching in an iterative way is possible, but I really need it for my special usecase.

Any help is greatly appreciated.



Solution 1:[1]

you could use the switchMap operator to return an array of actions.

For example, instead of;

    deleteMovie$ = createEffect(() => this.actions$.pipe(
      ofType(MovieActions.deleteMovie),
      mergeMap(({movieToDelete, search, page, limit}) =>
        this.moviesService.deleteMovie(movieToDelete)
        .pipe(
          map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
          map(() => MovieActions.getMovies({search, page, limit})),
          catchError(() => EMPTY)
        )
      )
    )
  );

You could try;

    deleteMovie$ = createEffect(() => this.actions$.pipe(
      ofType(MovieActions.deleteMovie),
      mergeMap(({movieToDelete, search, page, limit}) =>
        this.moviesService.deleteMovie(movieToDelete)
        .pipe(
          switchMap(() => [MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete}), 
MovieActions.getMovies({search, page, limit})]),
          catchError(() => EMPTY)
        )
      )
    )
  );

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 Mehmet YILMAZ