React初心者のためのreact-routerの使い方
2015年1月、React ConferenceにてReact.jsでネイティブアプリが作れるようになると発表された。この発表を受けて最近何かと話題のReact.jsだが、リリースされたのは2013年であり、2009年にリリースされたAngularJSや、2010年のBackbonejsなどの他のjavascriptフレームワークに比べると新しく、まだネットに日本語の情報があまりない。ということで、React.jsのデファクトルーティングライブラリであるreact-routerの使い方についてまとめてみた。
目次
1.そもそもreact-routerとは2. react-routerのインストール方法
3. react-routerの使用例
4. react-routerのコンポーネント一覧
5. Routerのrunメソッド
1. そもそもreact-routerとは
react-routerは、React.jsのデファクトのルーティングライブラリである。Ember.jsのrouting APIを基に作られていて、ヘッダー、サイドバー、フッターなどが複雑にネストされたビューのルーティングの設定を容易にしてくれる。なぜ容易になるのかというと、ビューのコンポーネント(ヘッダー、サイドバー、フッター等)のネスト構造と同じように、ルーティングの設定もネスト構造で定義することで、両者の関係性が単純化されるからである。
2. react-routerのインストール方法
それでは、さっそくreact-routerを触ってみよう。インストール方法はいたって簡単で、パソコンにnode.jsさえインストールされていれば、
npm install react-router
でインストールできる。
また、以下説明する例を試すにはjsファイルの先頭において以下をrequireしなければならない。
var Router = require('react-router'); var Route = Router.Route; var NotFoundRoute = Router.NotFoundRoute; var DefaultRoute = Router.DefaultRoute; var Link = Router.Link; var RouteHandler = Router.RouteHandler;
これは、CommonJSという、JavaScriptで様々なアプリケーションを作るための標準仕様に則っている。
3. react-routerの使用例
では、実際にどのように使われているのか。Dashboard・Inbox・Calenderの3つのページからなる、小さなWEBアプリケーションを例に説明する。以下の図が、そのアプリケーションのUIの設計図であり、全てのページで共通のヘッダーが使われるとする。
var Header = React.createClass({ render: function () { return ( <header> <ul> <li><a href="/">Dashboard</a></li> <li><a href="/inbox">Inbox</a></li> <li><a href="/calendar">Calendar</a></li> </ul> Logged in as Jane </header> ); } }); var DashboardRoute = React.createClass({ render: function () { return ( <div> <Header/> <Dashboard/> </div> ); } }); var InboxRoute = React.createClass({ render: function () { return ( <div> <Header/> <Inbox/> </div> ); } }); var CalendarRoute = React.createClass({ render: function () { return ( <div> <Header/> <Calendar/> </div> ); } }); otherRouter.route('/', function () { React.render(<DashboardRoute/>, document.body); }); otherRouter.route('/inbox', function () { React.render(<InboxRoute/>, document.body); }); otherRouter.route('/calendar', function () { React.render(<CalendarRoute/>, document.body); });
見て分かるように、この場合各コンポーネントで共通のヘッダーを呼びださなければならず、コードの重複が増えてしまう。
これに対しreact-routerを使うと、ルーティングを定義するコードは以下のようになる。
var Router = require('react-router'); var DefaultRoute = Router.DefaultRoute; var Link = Router.Link; var Route = Router.Route; var RouteHandler = Router.RouteHandler; var App = React.createClass({ render: function () { return ( <div> <header> <ul> <li><Link to="app">Dashboard</Link></li> <li><Link to="inbox">Inbox</Link></li> <li><Link to="calendar">Calendar</Link></li> </ul> Logged in as Jane </header> //<RouteHandler/>コンポーネントをrenderすることで、 //ルーティングで定義された全てのアクティブな子コンポーネントを呼び出す。 <RouteHandler/> </div> ); } }); //アプリケーションのurlの階層構造をネストされた<Route/>タグで定義し、 //各<Route/>のhandlerにReactのコンポーネントを紐付け、 //render時には、アクティブな<Route/>のhandlerがコンポーネントを呼び出し、 //それらが融合されて表出される。 var routes = ( <Route name="app" path="/" handler={App}> <Route name="inbox" handler={Inbox}/> <Route name="calendar" handler={Calendar}/> <DefaultRoute handler={Dashboard}/> </Route> ); //React RouterはリクエストされたURLに最も深くマッチする<Route/>を探し出し、 //その木構造の中での枝に含まれる全ての<Route/>をアクティブにする。 Router.run(routes, function (Handler) { React.render(<Handler/>, document.body); });
例として挙げたアプリケーションが単純なUIなため、コード量としてはさほど変わってはいないが、react-routerを使用することで、一箇所でルーティングを管理することが可能となり、ネストされたUIを作るときの生産性、保守性が上がる。また、ルーティングを設定しないとビューが表出されないことから、URLの構造を先に考えつつ開発を行う事ができる。これらのメリットは、UIが複雑になればなるほど役立つものとなる。
4. react-routerのコンポーネント一覧
2. Link
4. DefaultRoute
5. NotFoundRoute
6. Redirect
8. Navigation
1. RouteHandler
<RouteHandler/>は、その子要素のアクティブな <Route />のハンドラーを呼び出す。
2. Link
<Link >はtoオプションで指定したnameの <Route >のハンドラーを呼び出す。
// このようなルーティングの設定があった場合 <Route name="user" path="/users/:userId"/> // 以下のリンクコンポーネントで、上記の<Route/>のハンドラーを呼び出せる。 <Link to="user" params={{userId: "123"}}/>
paramsオプションに対しては、渡したいRouteのpathのダイナミックセグメントと一致するname,valueのオブジェクトを渡す。
//ダイナミックセグメントとは、pathの一部で:から始まるId等を指定している箇所のこと <Route name="user" path="/users/:userId"/> //このRouteの場合、:userIdの部分を示す。
3. Route
<Route handler={App}> <Route name="about" handler={About}/> //pathが指定されていない場合、pathはnameから自動的に補完される。 //この場合<Route name="about" path="about" handler={About}/>となる。 <Route name="users" handler={Users}> <Route name="user" handler={User} path="/user/:id"/> </Route> </Route>
<Route >はそのネスト構造によりアプリケーションのルーティングを定義しとhandlerでviewの階層構造を定義する。
<Route />のオプション
path: ドメイン以下のurl。未定義の場合、nameから定義され、nameも未定義の場合、デフォルトで'/'になる。
handler: routeがアクティブなときに呼び出されるコンポーネント。
4. DefaultRoute
<DefaultRoute>は親のrouteのpathと完全に一致する時アクティブになる。
<Routes> <Route path="/" handler={App}> <!-- pathが'/'の時、以下の<DefaultRoute handler={Home}/>がアクティブになる。 --> <DefaultRoute handler={Home}/> <Route name="about" handler={About}/> <Route name="users" handler={Users}> <Route name="user" handler={User} path="/user/:id"/> <!--pathが'/user'のとき、以下の <DefaultRoute handler={Home}/>がアクティブになる。--> <DefaultRoute name="users-index" handler={UsersIndex}/> </Route> </Route> </Routes>
5. NotFoundRoute
<lNotFoundRoute>は、リクエストされたurlが親の<Route/>のpathとマッチするのに、そのいずれの子<Route/>ともマッチしない場合にアクティブになる。エラーページの作成等に使える。
<Route path="/" handler={App}> <Route name="course" path="course/:courseId" handler={Course}> <Route name="course-dashboard" path="dashboard" handler={Dashboard}/> <!-- `/course/123/foo` というurlがリクエストされた場合、 以下の <NotFoundRoute />がアクティブになる。--> <NotFoundRoute handler={CourseRouteNotFound} /> </Route> <!-- `/flkjasdf`というurlがリクエストされた場合、 以下の <NotFoundRoute />がアクティブになる。 --> <NotFoundRoute handler={NotFound} /> </Route>
6. Redirect
<Redirect>は、fromオプションで設定したpathへのリクエストがあったときに、toオプションで指定したpathにリダイレクトするようにする。
<!-- 開発中にurlの名称等を変更したくなった場合に使える。 `/get-in-touch`というpathにリクエストを送ると 、 `/contact`というpathをrenderするようにする。 --> <Route handler={App}> <Route name="contact" handler={Contact}/> <Route name="about-user" path="about/:userId" handler={UserProfile}/> <Route name="course" path="course/:courseId"> <Route name="course-dashboard" path="dashboard" handler={Dashboard}/> <Route name="course-assignments" path="assignments" handler={Assignments}/> </Route> <!-- `/get-in-touch` -> `/contact` --> <Redirect from="get-in-touch" to="contact" /> </Route>
7. State
アクティブなparams,query,routeの情報を必要とするコンポーネントのためのmixin。ダイナミックセグメントを含む<Route>のhandlerが呼び出すコンポーネント等で使われる。
// route <Route name="user" path="user/:name" handler={User} /> // handler var User = React.createClass({ //mixinは、mixinsに配列で渡す。 mixins: [ Router.State ], render: function () { //アクティブなparamsの情報を取得している。 var name = this.getParams().name; return ( <div> <h1>{name}</h1> </div> ); } });
<State />のインスタンスメソッド
getParams: アクティブなparamsを返す。
getQuery: アクティブなqueryを返す。
5. Routerのrunメソッド
最後にRouterのrunメソッドについて紹介する。runメソッドは、リクエストされたURLとマッチするrouteを特定し、それらのhandlerに紐づくコンポーネントをラップし、コールバックにhandlerとstateを引き渡す。
Router.run(routes, [location,] callback(handler, state)) //第二引数のHistoryLocationによって、HTML5のhistory APIを使えるようになる //第三引数のコールバック関数である無名関数の第一引数はHandlerで、 //マッチした<Route/>の全てのコンポーネントがラップされている Router.run(routes, HistoryLocation, function (Handler) { // whenever the url changes, this callback is called again React.render(<Handler/>, document.body); });
参照URL
以上