ApplicationクライアントアプリケーションでもReudxを使用する。Redux自体がどのように働くかはすでに見た。Reduxは、Reactとどのように合わさるのか、Reactアプリのデザインにどのように影響するのか見ていこう。Setupまずは、プロジェクトのセットアップ。-yアプリのホストページとなるHTMLを作成しよう。src="bundle.js"></script></body></html>アプリケーションのエントリーポイントとなるJavaScriptファイルを作成しよう。alive!');クライアント開発にWebpackを使用する。必要な物をインストールしよう。webpack-dev-server次に、Webpack設定ファイルをプロジェクトのルートに作成する。}};index.jsをエントリーポイントとして、すべてをdist/bundle.jsファイルにバンドルする。ディベロップメントサーバーのベースとしてdistディレクトリを用いる。bundle.jsを作成するにはWeboackを実行する。webpackディベロップメントサーバーを開始するには次のコマンドを実行する。webpack-dev-serverクライアントでは、ES6とReactのJSX構文を使用するため、Babelを用いる。babel-preset-reactpackage.jsonにBabelのプリセットを指定する。"react"]}Webpack設定ファイルを修正する。supportクライアントコードでもユニットテストを記述する。コンポーネントも同様にテストする。jsdomReactを使用する前にjsdomのセットアップが必要だ。ウェブブラウザに標準で提供されているdocument/windowオブジェクトをグローバルオブジェクトに指定し、Reactからアクセスできるようにする。win;加えて、navigatorといったjsdomのwindowオブジェクトがもつすべてのプロパティを取り、それらをNode.jsのグローバルオブジェクトにまで引き上げる。することでwindowなしでもプロパティを使用することができる。}});immutableとchai-immutableをインストールし、test_helper.jsファイルを修正する。chai-immutableテストを実行するためのコマンドを追加しよう。--watch"},これはサーバーのpackage.jsonのコマンドとほとんど同じもの。違う点はサーバーでは、--recursiveを使い、.jsxファイルを入れない。すべての.js/.jsxテストファイルを取り込むためにglobを使う。react-hot-loaderWeboackとBabelインフラを設定したら、次はReactについて。ReduxとImmutableによるReactアプリケーションでは、ピュアコンポーネントを記述する。コンセプトとしては、これはピュア関数と似ている。関数がデータを引数に取るように、ピュアコンポーネントはデータをプロパティ(props)として受け取る。ピュアコンポーネントは内的なstateをもたず、受け取ったプロパティによって描画が変わる。storeのimmutableデータ構造の中だ。Reactコンポーネントは与えられたstateの、statelessな投射である。プロジェクトにReactを追加しよう。react-domreact-hot-loaderもセットアップする。現在のstateを失わずにコードをリロードすることでき、ディベロップメントワークフローをかなり速くしてくれる。react-hot-loaderreact-hot-loaderを使用するために、コンフィグファイルを修正する。]};entryセクションでは2つ、新たに追加している。loaderを読み込んでいる。(HMR)に必要なインフラを提供する。true)にさせておく必要がある。loaderを設定している。Screenアプリケーションの投票UIは極めてシンプル。投票中は2つのボタンが表示され、それぞれに対して投票がなされる。投票が終了すれば、winnerが表示される。ここまで主にテストファースト開発を行ってきたが、Reactコンポーネントに対しては先にコンポーネントを記述してから、テストを記述する。loopを行うためである。UIを実際に見て確かめる以上のフィードバックはない。アプリケーションのエントリーポイントにVotingコンポーネントをレンダリングする。divにマウントする。JSXマークアップを使用しているため、index.jsをindex.jsxにリネームする。document.getElementById('app'));Votingコンポーネントは現在のエントリーペアをpropsとして受け取る。現状、入力ペアをハードコーディングしておくが、後で本当のデータと入れ替える。webpack.config.jsのエントリーポイントのファイルネームも変更しておく。'./src/index.jsx'],wepack-dev-serverをリスタートすると、Votingコンポーネントがないためにエラーを吐く。}});ペアエントリーがボタンとしてレンダリングされているのが、ウェブブラウザーで見ることができるはずだ。変更を加えればすぐに反映されるのがわかる。ひとつ目のユニットテストを記述しよう。{});pairプロパティに基づいてボタンを描画するコンポーネントをテストするために、このコンポーネントを描画して、出力を確認する。ユニットテストにおいてコンポーネントを描画するために、renderIntoDocumentと呼ばれる関数を使用する。});});コンポーネントが描画されたら、scryRenderedDOMComponentsWithTag関数を使ってbuttonエレメントを取得し、テクストをそれぞれテストする。});});テストを実行して、通ることを確認しよう。testボタンのひとつがクリックされたら、コンポーネントはコールバック関数を発火する。エントリーペアと同じように、コールバック関数もプロパティとしてコンポーネントに与えられる。これに対してもユニットテストを記述する。Simulateを使って、クリックイベントをシュミレートする。});});このテストを通すために、現在のエントリーにvoteを発火するonClickハンドラを設定する。}});ユーザーがすでにペアのどちらかに投票をしていれば、それ以上の投票をさせるべきではない。コンポーネント内でこのロジックを完結することもできるが、コンポーネントをピュアに保つために、外部に表そう。コンポーネントはhasVotedプロパティを取り、値は今のところはハードコーディングしておく。document.getElementById('app'));簡単に実装することができる。}});ユーザーが投票したボタンに小さなlabelを加え、どちらに投票したのかをわかりやすくしよう。labelはhasVotedプロパティのエントリー一致したボタンの下に表示される。}});最後に、winnerが決まったらボタンではなくwinnerのみを描画するようにしよう。値はハードコーディングしておく。}});少しコードが複雑になってきた。ここで、このコンポーネントからWinnerコンポーネントとVoteコンポーネントを切り出そう。投票スクリーンはどちらかを描画する。}});Voteコンポーネントはほとんど前のVotingコンポーネントと同じ。}});Votingコンポーネントはどちらを描画するのかを選択する。}});Winnerコンポーネントにrefを追加している。これはユニットテスト内でDOMを取得するために使用する。ユニットテストを記述しよう。はじめに、hasVotedプロパティがあれば、ボタンはdisabled(使用不可)になる。labelはhasVotedの値が一致したエントリーのボタンに表示される。refのエレメントが表示される。dataとReactを併用することの利点はもう一つある。dataを使用し、コンポーネントをピュアコンポーネントとして記述すれば、Reactはプロパティの変化を察知するために使用することができる。PureRenderMixinは、そのために使われる。定義として、不変データ構造内では変化が生じないために、コンポーネントのプロパティはすべて変化しない値であり、再描画する必要が無い。ユニットテストを記述し、具体的に確認しよう。このコンポーネントはピュアであり、変化する配列を入れ、その中で変化しても、再描画するべきではない。listをセットする。});});今のままでは、テストを実行しても、両方のケースで再描画するので期待通りにはならない。パッケージをインストールしよう。react-addons-pure-render-mixinこのmixinをそれぞれのコンポーネントに導入すれば、テストは通る。Routing結果が表示されるスクリーンに移ろう。投票スクリーンで表示されるペアと同じものと、それぞれの投票結果に加えて、投票を管理する人にのみ、次のペアに移るためのボタンが表示される。投票スクリーンの表示にルートパス#/を設定し、結果スクリーンを#/resultsに設定する。異なったコンポーネントを異なったパスに結ぶために、react-routerライブラリを使用する。react-router@2.0.0Routeと呼ばれるReactコンポーネントを用いて、ルーティングテーブルを定義する。document.getElementById('app'));Votingコンポーネントに対するシングルルートを作成した。Routeのコンポーネントを定義している。Routeコンポーネントを作成する目的は、すべてのRouteに共通のマークアップを描画するため。}});このコンポーネントはchildrenプロパティとして与えられたchildコンポーネントを描画する以外には何もしていない。今のところはVotingコンポーネントのRouteしかないため、常にVoitngを描画している。pairデータのplaceholderはindex.jsxからApp.jsxに移している。APIを使って、もとのコンポーネントを複製する。これは一時的なもので、後に取り除く。index.jsxに戻って、Routeに手を加えよう。document.getElementById('app'));rootコンポーネントとして、Routerコンポーネントを供給し、#hashベースのヒストリーメカニズムを利用している。新しくResultコンポーネントをRouterに追加する。document.getElementById('app'));ここではやはり<Route>コンポーネントを使用し、/resultsパスにResultsコンポーネントを指定している。簡単にResultsコンポーネントを作成して、ルーティングを確かめてみよう。}});ブラウザでhttp://localhost:8080/#/resultsを開くと、Resultsコンポーネントからのメッセージが表示されるはずだ。pathは投票ボタンを表示している。次にResultsコンポーネントを使えるものにしよう。投票中のエントリーがまず表示される。}});これは結果スクリーンなので、投票数も表示するべきだ。}});これらの数字を表示させるために、Resultsコンポーネントを調節しよう。}});ここまで、現在のResultコンポーネントの振る舞いに対してのユニットテストを追加してきた。それぞれのentryに対して、divエレメントを描画し、両方のentryの名前と投票数を表示する。投票がないentryに対しても、投票数ゼロを表示する。});});次に、"NEXT"ボタンについて話を進めよう。コンポーネントのプロパティにコールバック関数を置いて、"NEXT"ボタンがクリックされたら、そのコールバック関数を発火する。これについて、投票ボタンとよく似た形でユニットテストを記述することができる。});});実装についても、投票ボタンとほとんど同じ。引数がないので幾分かはシンプルなものになる。}});最後に、投票スクリーンと同じく、結果スクリーンにもwinnerを表示する。expect(winner.textContent).to.contain('Trainspotting');});すでに投票スクリーンに使用したWinnerコンポーネントを再利用すれば、簡単に実装することができる。winnerがあれば、通常の結果スクリーンに変わり、それを描画する。}});実際のデータやアクションと結びついていないため、これらのコンポーネントは全く動作をしない。ここまでは、ただシンプルなプレースホルダのデータをコンポーネントに入れて、UIの構造を具体化したにすぎない。storeに入力・出力を結びつけて、UIに命を吹きこもう。