react-railsでisomorphicなwebを入門してみる

React.jsが流行ってますね。React.jsは「単一方向データフロー」であることと、フルスタックではない「UIライブラリ」であることがAngularJSなどとの違いだと思っております。このへんは詳しい記事をググって下さい(無責任)。 
 Railsな人の為にオフィシャルでreact-railsというgemがあるのでこちらでサクッと入門してみましょう。

react-rails

最初にやることとしては公式のチュートリアルがあります。Reactの公式ページはかなり充実してる上に読みやすく気合を感じます。

自分はmarkdownにするとことか省いてみてサクッと作ってみました。

準備

$ rails new react_sample -d sqlite3 --bundle-skip -T

Gemfile

gem 'haml-rails'
gem 'react-rails', '~> 1.0.0.pre', github: 'reactjs/react-rails'

細かいとことrails側のコードは省略します。最後の参考にあげたQiitaの記事を参考にしたので是非そちらをストックするなりすると良いと思います。自分はhamlの人なのでhamlを使用します。

Rails側の準備

$ bundle install
$ rails g react:install
$ rails g controller Dashboard index
$ rails g react:component Chat
$ mv app/assets/javascripts/components/chat.js.jsx app/assets/javascripts/components/chat.js.jsx.coffee
$ rails g model Comment author:string text:text
$ rails g model Comment author:string text:text
$ rails g controller Api::Comments index

で、本題のcomponents/chats.js.jsxが以下になります。 先のrails g react:component Chatで生成されるファイルです。

CommentBoxなどがcomponentと呼ばれるもので、compenentはrenderメソッドで文字通りレンダーされる要素を返します。また、componentにはPropとStateがあって、Propが引数的なものだったりinterface的なものでStateがreactiveに変わる要素だとざっくり理解しました。あと気になるのは、投稿時の処理をCommentFormがCommentBoxに移譲しているのも特徴でしょう。

このへんは一人React.jsという神アドベントカレンダーが大変参考になるので、またこちらでちゃんと理解しとくことにします。

で、とりあえず出来ました。絶望的に無味乾燥なコメント投稿システムです。

Isomorphic

Isomorphicとはクライアントとサーバーサイドを同時に記述していく考え方で、「マジすげーじゃん!」と思うのだけど、賛否両論あったりなものです。ただ、AngularJSなどシングルページアプリケーションを書いてみた後だと以下2点に関してはビビッと惹かれるのではないでしょうか。

AngularJSだとロードされるまでにng-cloakで要素を隠したりするんだけど、1msでも速くユーザーが視界に入るのを期待している要素はあるよね、ってことで、それをサーバーサイドでフロントと同じ記述でrender出来るのはハイパー素敵!

フルAngularJSのサービスが悩まされるのがSEOで、最近はちゃんとクロールしてくれるようになったり、対策すれば問題ないのかもしれないけど、比較的staticなhtmlがクロールされている方が心が穏やかになる。

で、なんでこういう話をするかというとreact-railsにはrails側でreactのcomponentをrenderするreact_componentというヘルパーメソッドがあるのです。これは感動するでしょう?

ということで書き換えていきます。

  • jQueryのonloadでcomponentのrenderをしてたので、いきなり$がないと怒られる。renderは書かないようにした。
  • jsxだとうまくいくんだけど、jsx.coffeeだとコンポーネントがないとか言われるのでexecJSが対応してないのかなと思ってsprockets-coffee-reactを入れる。これはたぶん勘違いで下のが原因だったかもだけど、入れたままにしてる。
  • windowにぶら下げて無いとexecJSが見つけてくれないようなのでwindowにCommentBoxをぶら下げてみた。これが最善なのか謎。

書き換えた後のchat.js.jsx.coffee

書き換えた後のindex.html.haml

%h1 Rails React Chat
= react_component "CommentBox", { url: "/api/comments", pollInterval: 2000 }, {prerender: true}

これで、JSがロードされる前でもcommentというh1タグが表示されます。application.jsのロードをコメントアウトしてもh1タグが表示されるのが確認出来るでしょう。

以上なのです。

最後に

今回書いたアプリケーションは以下にあります。

https://github.com/imaimiami/react-rails-chat

今回はcomponentを一つのファイルにまとめてるのですが、適切に分割してあげるとよさげです。で、個人的にはanimationどうやるのとか、material designのライブラリ試したいとか寄り道的なとこに興味があってこれ書き始めたんですが、予想外に長くなったのでそのへんはまた別で書いてみます!せつない!

ではまた!! (バーミヤンで青椒肉絲を食べながら)

参考

http://bensmithett.com/server-rendered-react-components-in-rails/ 
 http://qiita.com/mmyoji/items/ce7fef70c0c91aca793b 
 http://qiita.com/advent-calendar/2014/reactjs


Originally published at imaimiami.com on March 15, 2015.