React.jsは、ネイティブアプリのようにインタラクティブなUIを作りやすくするためのJavascriptライブラリです。
従来、Webサービス分野ではjQueryが近い機能を果たしてきましたが、React.jsはJSXの導入によりDOM操作に引きずられることなく、より凝集性の高いコードを書けるよう設計されています。
Railsプロジェクトとの組み合わせ方
RailsプロジェクトとReact.jsベースのクライアントコードは大ざっぱに分けて、以下のような3つのパターンが考えられ、それぞれメリット・デメリットがあります。
- react-railsを利用してAsset Pipelineに組み込む
- Railsのビルド手順に組み込まれるため、新たに準備すべきものは少ない。一方、Javascript側のツールチェインをうまく使えず柔軟性が低い
- SPAのようにJavascript主体でアプリを作り切り、RailsをAPIサーバにする
- クライアントとサーバサイドのコードを完全に分離するため、保守性の高いアーキテクチャにしやすい期待はある。ただし初物のツールの割合が多くなり目先は不透明
- RailsのViewの部品としてReactjsコンポーネントを埋め込む
- アプリの基本設計はRailsそのものを流用できる。各ページ内の処理がRubyとJavascriptに分かれるため、保守性は下がる
今回は、既存プロジェクトのコードベースを生かすことを重視して、3番目のアプローチを採りました。
相対的にReact.jsの実績が乏しくJavascriptスタック主体で完成度を上げることが難しい現状では2番目のアプローチはとりづらく、逆に1番目のreact-railsではツールの選択肢が狭すぎるため、React.jsから見たオーソドックスな手法から外れてしまう懸念がありました。
既存のViewにReact.jsのコンポーネントを組み込む
React.jsのUIコンポーネントを標準的な手順で開発したら、RailsのViewに組み込む手順は比較的シンプルです。
要点だけに簡略化すると、コンパイル済のjsコードをインクルードして、コンポーネントを表示するためのユニークな空タグを出力するだけです。
<script src="/assets/javascript/bookmark_component.js"></script>
<div id="bookmark_button"></div>
このViewに対応する、bookmark_component.jsxのインターフェースは以下のようになります。ReactDOM.render()
の中でgetElementById()を用いて表示するDOMを指定するだけです。
var Bookmark = React.createClass({ // コンポーネント定義 });
ReactDOM.render( (<Bookmark />),
document.getElementById('bookmark_button')
);
React.jsで本格的に開発していこうと考えると、おそらくJavascript側のツール整備やコードが大きくなっていくので、Railsとの接点はなるべくシンプルにしておくべきという印象です。
DOM経由でRailsの値をReact.jsに渡す
この方式で実装する場合、サーバサイドの変数をJavascriptに渡すことが難点になりがちです。
サーバーからの値の取得は、原則としてRails側でAPIを用意してAjaxで取得すべきなのですが、実験的にReact.jsを導入したい段階でAPIを開発するのが難しいというケースがあります。
その場合、DOMにERBで変数を出力しておき、Javascriptから読んでStateにセットする、という手法が使えました。(もっとも、React.jsは脱DOMを指向しているのでこれはアンチパターンの可能性もあります)
具体的な手順として、Rails側ではViewに<span id="object_id" reactdata="<%= @some_object_id %>"></span>
のようなタグを出力しておきます。
React.js側ではReactコンポーネントのgetInitialState
でDOMから値を読み出してStateにsetすることで、一般的なReactの変数として使えるようになります。
var Bookmark = React.createClass({
getInitialState: function() {
return {
objectid: document.getElementById("object_id").getAttribute("reactdata")
};
},
// コンポーネント定義 });
まとめ
React.jsをRailsプロジェクトに導入する手順の要点を紹介しました。
じっさいにはJavascriptのツールチェインを用意してワークフローを準備することもそれなりに手間がかかります。
ツール不足という側面よりも、クライアントサイドとサーバサイド間のコード構造が違うことの方がより時間のかかる課題という印象です。
けっきょくのところ、React.jsを導入したい目的には「jQueryの水準を大きく超えるインタラクティブなUIを実装したい」という意図があるはずで、これは本質的にView層のコードをかなりたくさん書こうとしていることになります。
複雑性が増すのはある意味当然なので、React.jsとRails間のインターフェースが疎結合になるように設計することが重要になります。
Chuma Takahiro