16

状態項目を Angular 2 アプリに保存するために、次のレデューサーを作成しました。項目は、金融商品 (株式/通貨など) の価格オファーです。

私のレデューサーの実装は次のとおりです。

export const offersStore = (state = new Array<Offer>(), action:Action) => {
switch(action.type){

    case "Insert":
        return [
            ...state, action.payload
        ];
    case "Update":
            return state.map(offer => {
                    if(offer.Instrument === action.payload.Instrument)
                    {
                        return Object.assign({}, action.payload);
                    }
                    else return offer;
            });
    case "Delete":
        return state.filter(offer => offer.Instrument !== action.payload )
    default:
        return state;
    }

}

簡単ではありませんでしたが、なんとか挿入、更新、および削除を機能させることができました。Redux は、私が何年もコーディングしてきた方法から離れたパラダイム シフトのようなものだと思います。

アプリにインストゥルメント コンポーネント/ページがあります。このページには、InstrumentId ("EUR/USD" など) (payload.Instrument プロパティに格納されている) で示される、1 つの特定のインストゥルメントに関するすべての利用可能な情報が表示されます。

私の問題は、特定の楽器を効率的に検索して店から持ち出す方法がわからないことです。これだけでなく、サーバーからの websocket プッシュを介して頻繁に更新されるため、ストア内の Instrument が更新された場合、フェッチする Instrument も更新されるようにしたいと考えています。そのため、ストアにプッシュされた新しいデータに基づいてビュー コンポーネントを更新し続ける特定の機器をストアで検索し、それを Observable として返す必要があります。

どうすればこれを達成できますか?

4

2 に答える 2

8

さて、これを設定する方法を説明することに挑戦し、うまくいけば、あなたや他の人が理解できる方法でそれを行う.

したがって、オブジェクトの配列を格納していて、特定の ID またはキーによって行にアクセスする必要がある場合、ngrx サンプル アプリが示す方法は、使用するオブジェクトを含むオブジェクトを作成することです (この場合、書籍アプリの) 書籍の ID をプロパティ キーとして使用します。プロパティ名として任意の文字列を設定できます。つまり、値が空のオブジェクトである「エンティティ」と呼ばれるプロパティを持つ状態があるとします。次に、配列を取得して、「entities」オブジェクトにプロパティを作成できます。

export interface BooksState {
  entities: { [id: string]: Book };
};

book オブジェクトの配列の 1 行だけから始めましょう。この行を「entities」オブジェクトに追加するには、次のようにします。

 reducerState.entities[book.id] = book;

上記は、書籍の ID を「entities」オブジェクトのプロパティにします。
コンソールまたはデバッグ ツールで調べると、作成後に次のように表示される場合があります。

 reducerState.entities.15: { id: 15, name: "To Kill a Mockingbird" }

ngrx サンプル アプリは、完全な配列を操作して、javascript 配列の reduce 演算子を使用して状態に追加します。

   const newBookEntities 
              = newBooks.reduce(
                  (entities: { [id: string]: Book }, book: Book) => 
                           { 
                              return Object.assign(entities, { [book.id]: book }); 
                           }, {});

そして、必要な特定の行を取得するために後で一緒に構成できるこの状態の部分を取得する特別な関数を作成します

export function getBooksState() {
  return (state$: Observable<AppState>) => state$
    .select(s => s.books);
}


export function getBookEntities() {
  return (state$: Observable<BooksState>) => state$
   .select(s => s.entities);
};
export function getBooks(bookIds: string[]) {
  return (state$: Observable<BooksState>) => state$
              .let(getBookEntities())
              .map(entities => bookIds.map(id => entities[id]));
   }

そして、これらは例の index.ts バレルで構成されます

import { compose } from '@ngrx/core/compose';


export function getBooks(bookIds: string[]) {
   return compose(fromBooks.getBooks(bookIds), getBooksState());
}

この関数は、呼び出しを右から左に連鎖させます。最初に getBooksState を呼び出してレデューサーの状態を取得し、次に fromBooks.getBooks を呼び出して、必要な bookid と前の「getBooksState」からの状態を渡し、必要な選択された状態へのマッピングを実行できるようにします。

コンポーネントでは、この関数をインポートして、必要な本だけを取得するために使用できます。

myBooks$: Observable<Books>  =  this.store.let(getBooks(bookIds)));

この返されたオブザーバブルは、ストアが更新されるたびに更新されます。

追加:したがって、ストア オブジェクトの演算子「let」は、ストアの状態オブジェクトを保持する現在のオブザーバブルを、「getBooks」関数によって返される関数に渡します。

それを詳しく見てみましょう。

export function getBooks(bookIds: string[]) {
   return compose(fromBooks.getBooks(bookIds), getBooksState());
}

ここでは、2 つの関数 fromBooks.getBooks(bookIds) と getBooksState() が作成関数に渡されます。compose 関数を使用すると、右側の最初の関数に値を渡すことができ、その関数の結果を左側の関数に渡すことができます。したがって、この場合、「getBooksState」によって返される関数の結果を取得し、それを関数「fromBooks.getBooks(bookIds)」によって返される関数に渡し、最終的にその結果を返します。

これら 2 つの関数は、Observable を受け取ります。getBooksState() によって返される関数の場合、ストア状態の監視可能なオブジェクトをパラメータとして取り、そこから対象のストアのスライスにマップ/選択 (マップと選択は互いのエイリアス) して返します。新しいマップされたオブザーバブル。そのマップされたオブザーバブルは、fromBooks.getBooks(bookIds) 関数から返される関数に渡されます。この関数は、状態スライスが観測可能であることを期待しています。この関数は、関心のあるエンティティのみを引き出すことによって、新しいマッピングを行います。この新しいオブザーバブルは、「store.let」呼び出しによって最終的に返されるものです。

さらに明確にする必要がある場合は、質問してください。明確にするために最善を尽くします。

https://github.com/ngrx/example-app

于 2016-08-23T15:37:48.970 に答える