ここ数年、Javascript界隈でフレームワーク戦争が勃発してきました。クライアント開発の規模も年々大きくなり、jQueryだけでは複雑な画面遷移などを管理しきれなくなってきたのが原因だと思います。
私も昨年までAngularとbackboneを試しましたが、サーバサイドをMVCにしているのに、クライアントでもMVCを作るMVCの2階建ては、やり過ぎなのではないかと思っていました。フレームワークそのもの覚えるまでにも一苦労というのも面倒に感じました。
2014年、海外でブームに火が付いたReact.js
そんな中、2014年の後半からFacebook発のReact.jsの採用事例が聞こえてくるようになりました。AirBnBや米Yahoo! Mailなど大手がReact.jsを積極的に採用し出したので気になり、年末年始を使って色々調べてみることにしました。
Rails以来の衝撃
色々試していくうちにReact.jsは劇的にラクな事に気がつきました。そして既存のJSフレームワークより遙かに分かりやすい。初めてRailsを見たときと同じぐらいの衝撃がありました。
React.jsを一言でいうと「プログラムをAjax以前の構造に戻す」ことにあると思います。今までのフレームワークなどとパラダイムが大きく違うためちょっと理解するのに時間がかかりました。
なぜAjaxは難しいのか
React.jsの説明の前に今のWebアプリ環境を考えてみます。
Webアプリを作る場合には、PHPやRailsなどサーバ側でHTMLを生成してページ全体を遷移させる方法(サーバサイド生成)とAjaxを使う方法があります。同じ物を作るとしても、Ajaxの方が数段複雑です。
なぜ、サーバサイド生成に比べてAjaxは難しいのか整理してみました。
- DOMはどこからでも変更可能
- DOMが状態を持っている
- DOMとコードが離れすぎ
このような状態で画面の状態(DOM)を変えていくと、メンテナンスが非常に難しくなります。DOMはグローバル変数と同等なのに、競合なく書き換えるなんて不可能です。
サーバサイド生成はHTML作りっぱなし
それに対して、サーバサイドではHTMLを生成するだけです。そのHTMLの一部分だけでも変えたければ、サーバにリクエストして画面全部のHTMLを生成し直してもらう必要があります。
リンクを押したときに何が起こるのかも、hrefを見れば一目瞭然です。
サーバサイド生成と同じ仕組みをクライアントで
React.jsでは、サーバサイド生成と同じ流れをクライアント側で行います。
ロジック部分では、テンプレート変数にあたるstate(状態)を更新します。これを更新すると自動でrenderメソッドが呼ばれそこでHTMLを生成して表示します。
具体的なコードはこのようになります。React.jsではJSXというJavascriptの中にHTMLをかける仕組みを提供しています。初めは気持ち悪いですが慣れですw
JS Result
Edit on
/* ↑ Resultで実行結果が見られます */
/** @jsx React.DOM */
App = React.createClass({
/* stateの初期化 */
getInitialState: function() {
return {
switch1: true
};
},
handleSwitch1: function() {
this.setState({
switch1: !this.state.switch1 /* トグル処理 */
});
},
/* 画面を生成 */
render: function() {
return <div>
Switch1:
<button onClick={this.handleSwitch1}>
{this.state.switch1 ? "On" : "Off"}
</button>
</div>;
}
});
React.render(<App/>, document.body);
See the Pen React Toggle – 1 by Yuichiro MASUI (@masuidrive) on CodePen.
render
の中のHTMLにonClick
という昔はよく見かけたプロパティが見れます。若い人は見たことないかも知れませんが。
このボタンを押すと、this.handleSwitch1
メソッドが呼ばれます。その中ではsetState
メソッドを使ってswitch1
を更新しています。
setState
メソッドを呼び出すと、自動的にrender
メソッドが呼ばれ、画面が更新されます。
このようにReact.jsでは、いまの画面の状態を考える事無く、常に画面全体を生成していく仕組みになっており、これによりDOMの事を考える必要がなくAjaxを構築する工数を劇的に減らすことができます。
HTMLは全部再生成するけど、更新は差分だけ行われる
先の例ではスイッチを押すとrender
メソッドが呼ばれ画面全体が更新されます。
画面が簡素な時はいいですが、要素が増えてくると速度が心配ですし、CSSアニメーションなどは書き換えた時点で戻ってしまいます。
そこで、React.jsでは現在の画面と更新する画面の差分を取り必要な部分だけ更新するようになっています。このための仕組みがVirtualDOMです。
初めのうち、この仕組みを気にする必要はないと思います。
jQueryよりもずっと単純
このように画面を更新するのではなくrender
メソッドで新しい画面を生成するのは、jQueryでDOMを操作するよりずっと簡単に行えます。
画面を更新するのは全てrender
メソッド内で行われるので、画面を書き換えるときはそこだけを書き換えれば良いですし、ボタンをクリックしたときはonClick={...}
を追うと処理が見えます。
今までのフレームワークのように複雑な仕組みではなく、プログラムがシンプルになるのがReact.jsの大きな特徴です。画面を更新するためにエレメントにidを振らなくていいのでHTMLもシンプルになりあす。
良くあるTodoアプリもこれぐらいの長さで書くことができます。
See the Pen React Todo – 4 by Yuichiro MASUI (@masuidrive) on CodePen.
XHRで通信をしたりキャッシュなど複雑な機構を入れると、jQueryとの差がもっと開いていきます。
続きは
この記事では、Reactの一側面の概念だけを説明しました。
React.jsには、画面を部品単位に分けるCompoment、React.jsをベースにしたFluxフレームワーク、iOS/Androidアプリを作れるReactNativeなどまだまだ多くの機能があります。
もっと知りたい方は、公式ページが充実しているのでオススメです。日本語の情報だとQiitaのreactjsタグとkoba04さんの一人React.js Advent Calendar 2014が非常に参考になると思います。
Facebookが実際に利用しているのでヘビーにテストされていますし、速度向上の仕組みやデバッガなどがそろっているのも大きな魅力です。
私もReact.jsを触り始めたばかりですが、まずは検証を兼ねてwri.peをReact.jsで書き直し始めています。そこで得た知見を随時公開していきます。
もうすこし詳しいReact.jsってことでトレタ勉強会とか開いてみようかとおもうのですが、聞いてみたいと言う方いましたらコメントなどで残して貰えるとうれしいです。
一緒に働いてくれる方を大募集
私がCTOをしているトレタでは、Web予約を一緒に改善してくれるフロントエンドエンジニアとRailsエンジニアを募集しています。徹底的に使いやすい予約システムを一緒に作ってみませんか。
興味のある方は「トレタ」の進化を加速し、サービスの可能性を拡大するエンジニアを募集!をご覧下さい!一緒に働いてくれる方を待っています!
p.s
FacebookをReact debuggerで見るとVirtualDOMを見ることができます