web-dev-qa-db-ja.com

空のアクションをディスパッチする方法は?

ngrx/Effects を使用しています。

空のアクションをディスパッチするにはどうすればよいですか?

これが私が今している方法です:

 @Effect() foo$ = this.actions$
    .ofType(Actions.FOO)
    .withLatestFrom(this.store, (action, state) => ({ action, state }))
    .map(({ action, state }) => {
      if (state.foo.isCool) {
        return { type: Actions.BAR };
      } else {
        return { type: 'NOT_EXIST' };
      }
    });

アクションを返す必要があるため、return { type: 'NOT_EXIST' };を使用しています。

これを行うためのより良い方法はありますか?

12
Hongbo Miao

私は同様の未知のアクションを使用しましたが、通常はレデューサーの単体テストのコンテキストで使用します。

エフェクトで同じことを行うことに不安がある場合は、代わりにmergeMapObservable.of()、およびObservable.empty()を使用して条件付きでアクションを発行できます。

@Effect() foo$ = this.actions$
  .ofType(ChatActions.FOO)
  .withLatestFrom(this.store, (action, state) => ({ action, state }))
  .mergeMap(({ action, state }) => {
    if (state.foo.isCool) {
      return Observable.of({ type: Actions.BAR });
    } else {
      return Observable.empty();
    }
  });
10
cartant

私が探していた解決策は、@Effect({ dispatch: false })を使用することでした。

  @Effect({ dispatch: false })
  logThisEffect$: Observable<void> = this.actions$
    .ofType(dataActions.LOG_THIS_EFFECT)
    .pipe(map(() => console.log('logThisEffect$ called')));
4
ttugates

選択した回答は、rxjs6では機能しなくなりました。だからここに別のアプローチがあります。

別の回答で説明されているように、ほとんどの場合、フィルタリングを好みますが、flatMapを使用すると便利な場合があります。特に、複雑な作業を行う場合は、フィルター関数には複雑すぎます。

import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { flatMap } from 'rxjs/operators';
import { EMPTY, of } from 'rxjs';

@Injectable()
export class SomeEffects {
  @Effect()
  someEffect$ = this._actions$.pipe(
    ofType(SomeActionTypes.Action),
    flatMap((action) => {
      if (action.payload.isNotFunny) {
        return of(new CryInMySleepAction());
      } else {
        return EMPTY;
      }
    }),
  );

  constructor(
    private _actions$: Actions,
  ) {
  }
}
3

私はそれを次のようにします:

@Effect() foo$ = this.actions$
    .ofType(Actions.FOO)
    .withLatestFrom(this.store, (action, state) => ({ action, state }))
    .filter(({ action, state }) => state.foo.isCool)
    .map(({ action, state }) => {
      return { type: Actions.BAR };
    });

Ngrx 8以降、空のアクションをディスパッチしようとすると実行時エラーが発生するため、ディスパッチされないようにフィルターで除外するだけだと思います。

@Effect() foo$ = this.actions$.pipe(
    ofType(Actions.FOO),
    withLatestFrom(this.store, (action, state) => ({ action, state })),
    map(({ action, state }) => {
      if (state.foo.isCool) {
        return { type: Actions.BAR };
      }
    }),
    filter(action => !!action)
);
0
Antony