Angularアプリケーションで@ngrxを使用しています。すでに持っている繰り返しパターンの1つを抽象化したいと思います。
私の州は通常、次のような多くの州で構成されています。
myState: {
data: any
isLoading: boolean
isLoaded: boolean
}
コードでやっていることはそれをサブスクライブすることですが、状態がロードされた場合にのみ通知を受け取りたいです。
this.store
.select(state => state.myState)
.filter(myState => myState.isLoaded)
.map(myState => myState.data)
.do(data => do_whatever_I_need_to_do)
.subscribe();
これは私にとってはうまくいきますが、最初の3つの演算子は非常に反復的であるため、簡略化できるかどうか疑問に思いました。
セレクターを使用することで、次のようなものを作成できます
const selectMyState = (state) => state.myState;
export const getData = createSelector(selectMyState, state => state.data)
そしてそれをこのように使います
this.store
.select(getData)
.do(data => do_whatever_I_need_to_do)
.subscribe();
しかし、フィルター部分がないため、データがまだ読み込まれていない場合でも、フィルター部分からストリームイベントを取得する可能性があります。
その欠落しているフィルターをオブザーバブルに含める方法はありますか? createSelectorにはparamとしての関数があるため、そこでコードを実行できますが、それを使用してデータではなくイベント自体をフィルタリングする方法がわかりません。
何か案は?ありがとう!
ストリームの一部を再利用したいこの種のシナリオでは、ストアをパラメーターとして受け入れ、いくつかの操作を実行する関数を作成します。次に例を示します。
const selectMyState = (state) => state.myState;
export const getData = createSelector(selectMyState, state => state.data)
export const getDataWhenLoaded = (store) => {
return store.select(getData)
.filter(myState => myState.isLoaded);
};
...
getDataWhenLoaded(this.store).subscribe(...);
createSelector
関数の最後のパラメーターを使用する限り、必要に応じて行うことができます。 documentation では、createSelector
によって作成されたメモ化されたセレクターに渡された同じ状態は、プロジェクションを再計算しないことを述べています。呼び出されると、同じ値を返します。私はこれに関するドキュメントを見つけることができませんでしたが、テストを通じて、プロジェクションが以前の値と同じ値になる場合、サブスクリプションが既に以前の値を受け取っている場合は出力されないことに気付きました。 rxjs演算子distinctUntilChanged
と同様の動作。私は彼らのソースコードを掘り下げて、場所/方法/理由を理解する時間がありませんでした。
したがって、場合によっては、createSelector
の射影パラメーター(最後)にフィルターを配置できます。次に例を示します。
export const getActive = createSelector(selectMyData, state => state.data.filter(x => x.isActive));
例はngrx.ioからのものです
SelectValuesセレクターがあり、コードを再利用できるように値をフィルター処理するとします。
import { select } from '@ngrx/store';
import { pipe } from 'rxjs';
import { filter } from 'rxjs/operators';
export const selectFilteredValues = pipe(
select(selectValues),
filter(val => val !== undefined)
);
store.pipe(selectFilteredValues).subscribe(/* .. */);