web-dev-qa-db-ja.com

フィルター付きのngrxセレクター

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としての関数があるため、そこでコードを実行できますが、それを使用してデータではなくイベント自体をフィルタリングする方法がわかりません。

何か案は?ありがとう!

7
David

ストリームの一部を再利用したいこの種のシナリオでは、ストアをパラメーターとして受け入れ、いくつかの操作を実行する関数を作成します。次に例を示します。

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));
4
bygrace

例は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(/* .. */);
3
Max Epelbaum