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' };
を使用しています。
これを行うためのより良い方法はありますか?
私は同様の未知のアクションを使用しましたが、通常はレデューサーの単体テストのコンテキストで使用します。
エフェクトで同じことを行うことに不安がある場合は、代わりにmergeMap
、Observable.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();
}
});
私が探していた解決策は、@Effect({ dispatch: false })
を使用することでした。
@Effect({ dispatch: false })
logThisEffect$: Observable<void> = this.actions$
.ofType(dataActions.LOG_THIS_EFFECT)
.pipe(map(() => console.log('logThisEffect$ called')));
選択した回答は、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,
) {
}
}
私はそれを次のようにします:
@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)
);