6

How do I get my ngrx/store effect to dispatch an empty action? I'm running Angular 6/rxjs 6:

  @Effect()
  testEffect$ = this.actions$.ofType(FIRST_ACTION).pipe(
    map((x) => {
       if (x === y) {
          return new SECOND_ACTION;
       } else {
          fire.some.effect;
          return EMPTY;
       }
    })
  );

At the moment, I'm getting two errors: Effect "testEffect$" dispatched an invalid action: [object Object] followed by TypeError: Actions must have a type property.

I found this answer, but it doesn't seem to work with ng/rxjs 6. So far, I've tried the following (none work):

EMPTY, Observable.empty(), Observable.of() and Observable.of([]), { type: 'EMPTY_ACTION' }

Any help would be appreciated! I know I can use { dispatch: false }, but the actual effect has about five outcomes and only one of them doesn't use an action, so I'd rather have that last one return something as well.

Barruzi
  • 163
  • 2
  • 8
  • What's `fire.some.effect`? Is it `this.store$.dispatch`? – martin Jun 13 '18 at 09:35
  • https://stackoverflow.com/a/39762099/6680611 – cartant Jun 13 '18 at 10:20
  • @martin - No, it's a reroute: `this.router.navigate(['url']);` @cartant - Thanks for the link, but I already found your answer and I don't think it works with ng 6. At least none of the options you mentioned didn't do it for me. – Barruzi Jun 13 '18 at 10:51

3 Answers3

16

Here is a possible solution:

@Effect()
  testEffect$ = this.actions$.ofType(FIRST_ACTION).pipe(
    tap((x) => { // do some side effect here
        if (x !== y ) {
            fire.some.effect;
        }
    }),
    filter((x) => x === y), // proceed only if condition is true
    map((x) => {
       return new SECOND_ACTION; // then return the needed action
    })
  );
Anton Dosov
  • 326
  • 2
  • 6
3

you could just use filter

@Effect()
testEffect$ = this.actions$.ofType(FIRST_ACTION).pipe(
  filter(x => x === y),
  map( x => new SECOND_ACTION)
)

and if you still need the other case you can write another effect with dispatch: false

itay oded
  • 978
  • 13
  • 22
0

This works for me (ng6) :

@Effect()
boardOpened$ = this.actions$
  .ofType<BoardActions.Open>(BoardActions.OPEN)
  .pipe(
    withLatestFrom(this.store.select(BoardSelectors.getState)),
    map(([action, state]: [Action, BoardReducer.State]) => {
      return !BoardReducer.isLoaded(state)
        ? new BoardActions.Load()
        : EMPTY;
    })
  );

or

@Effect()
boardOpened$ = this.actions$
  .ofType<BoardActions.Open>(BoardActions.OPEN)
  .pipe(
    withLatestFrom(this.store.select(BoardSelectors.getState)),
    switchMap(([action, state]: [Action, BoardReducer.State]) => {
      return !BoardReducer.isLoaded(state)
        ? of(new BoardActions.Load())
        : EMPTY;
    })
  );
Thierry Falvo
  • 5,892
  • 2
  • 21
  • 39
  • Could you give some context as to what `EMPTY` is, or what package it comes from? – EHorodyski Dec 03 '18 at 19:58
  • do not use `EMPTY` as it completes the stream and no further events are listened! – Mateo Tibaquira Mar 16 '20 at 21:02
  • 1
    Mateo Tibaquira, sorry but I disagree. why ? Could you give some reference please? An HttpClient.get is also an observable that completes. See [https://ngrx.io/guide/effects#writing-effects](Official docs) that mentioned it to manage `catchError`. Thanks. – Thierry Falvo Mar 17 '20 at 06:57