前回記事はこちら
angular-redux/store
の@select
デコレーターの使い方について解説していきます。
バージョン情報
Angularをベースに、Reduxのアーキテクチャを採用しています。
Angular: 5.2.9
angular-redux/store: 7.1.1
Node: 8.1.4
Angular CLI: 1.7.3
サンプルアプリケーションについて
仮想通貨取引所のビットフライヤーとコインチェックのビットコイン価格を、WebAPIから取得して画面に表示するアプリケーションを例に説明します。
Stateの構造
本サンプルアプリケーションのState
は、2層にネストされていて、👇画像の構造になっています。
Stateのソースコード
1層目
Stateの一層目は、BitflyerTickerModel
型のbitflyerTicker
プロパティとCoincheckTickerModel
型のcoincheckTicker
プロパティで構成されています。
src/state/root/store.ts
:
import { BitflyerTickerModel } from '../bitflyer-ticker/bitflyer-ticker.model'; import { CoincheckTickerModel } from '../coincheck-ticker/coincheck-ticker.model'; export interface IAppState { bitflyerTicker: BitflyerTickerModel; coincheckTicker: CoincheckTickerModel; } export const INITIAL_STATE: IAppState = { bitflyerTicker: null, coincheckTicker: null, };
2層目
BitflyerTickerModel
型は、ビットフライヤーが取り扱っている通貨の価格を表していて、12個のプロパティを持っています。
src/state/bitflyer-ticker/bitflyer-ticker.model.ts
:
export interface BitflyerTickerModel { best_ask: number; best_ask_size: number; best_bid: number; best_bid_size: number; ltp: number; product_code: string; tick_id: number; timestamp: string; total_ask_depth: number; total_bid_depth: number; volume: number; volume_by_product: number; }
CoincheckTickerModel
型は、コインチェックが取り扱っている通貨の価格を表していて、7個のプロパティを持っています。
src/state/coincheck-ticker/coincheck-ticker.model.ts
:
export interface CoincheckTickerModel { last: number; bid: number; ask: number; high: number; low: number; volume: string; timestamp: number; }
ネストされたStateの参照方法
@select
を使って、Stateの最新の値を取得していきます。
@select
のオプションには、文字列データ、もしくは文字配列データを指定することができます。
src/app/app.component.ts
:
import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { BitflyerService } from './services/bitflyer.service'; import { CoincheckService } from './services/coincheck.service'; import { select } from '@angular-redux/store'; import { BitflyerTickerModel } from '../state/bitflyer-ticker/bitflyer-ticker.model'; import { CoincheckTickerModel } from '../state/coincheck-ticker/coincheck-ticker.model'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { // 2層目のltpプロパティを参照 @select(['bitflyerTicker', 'ltp']) readonly bitflyerLtp$: Observable<number>; // 1層目のcoincheckTickerプロパティを参照 // プロパティ名と変数名が同じため、selectorオプションは省略されている @select() readonly coincheckTicker$: Observable<CoincheckTickerModel>; // 1層目のbitflyerTickerプロパティを参照 @select('bitflyerTicker') readonly ticker$: Observable<BitflyerTickerModel>; constructor( private bitflyerService: BitflyerService, private coincheckService: CoincheckService ) {} ngOnInit() { this.bitflyerService.getTicker(); this.coincheckService.getTicker(); } }
各プロパティの初期値はundefined
のため、値が更新されるまでの間にエラーが発生するのを防ぐ目的で、Angularのsafe navigation operator(?.)
を使用しています。
src/app/app.component.html
:
<div>{{ bitflyerLtp$ | async | number }}円</div> <div>{{ (coincheckTicker$ | async)?.timestamp | date }}</div> <div>{{ (ticker$ | async)?.product_code }}</div>
動作確認
👆のソースコードを実行すると、@select
デコレーターによって、最新のStateの値が取得されていることがわかります。