ページ内画面遷移を実装する
開発環境が整ったところで、いよいよTODOアプリを仕上げていきましょう。その前に、アプリの仕様を再確認しておきます。
- トップページで新規TODOを登録する
- Doneボタンを押下するとTODOが完了状態になる
- 未完了のTODOはトップページ(#active)に、完了済のTODOは2ページ目(#completed)に表示する
まだトップページしか作っていませんので、まずは2ページ目に遷移できるようにしましょう。
シングルページアプリケーションにおけるRouterの概念
シングルページアプリケーションでは同一ページ内で画面を再描画するため、そのままではURLが切り替わらず、戻る・進むボタンなどの操作やブックマークができず不便です。そこで、多くのJavaScriptフレームワークではRouterと呼ばれる仕組みを用いて、URLを切り替えながらページ内の画面遷移を実現しています。これは、ちょうどサーバがリクエストされたURLに応じて処理を振り分ける動作を、クライアント側で再現したものです。
注意点としては、例えば/
から/foo
にページ内で画面遷移する場合と、/foo
に直接アクセスする場合とで、同じ画面が表示される必要があります。Routerが正しく機能しているかを確かめるには、次の操作を試してみてください。
- ブラウザの「戻る」「進む」「更新」ボタンを押したときにコンテンツが正しく切り替わる
- 新しいタブにURLをコピーしたときに同じ内容が表示される
サンプルではサーバー側の実装を省略するため、ハッシュリンクを使って画面を切り替える方式を採用しています[6]。
[6] ハッシュを用いる場合Routerの実装はhashchange
イベントを利用し、ハッシュを用いない場合Routerの実装はHTML5のpushState()
/popState()
を利用します。表面的なRouterの使い方はどちらも変わりません。
Routerを使ってページ遷移を実装する
React.jsはViewのみを扱うため、それ自体はRouterの機能を持っていませんが、外部ライブラリを使うことで、Router機能を容易に実現できます。ここでは、Routerライブラリの1つである「director」を使います。
var Router = require('director').Router; ... var App = React.createClass({ ... componentDidMount: function() { ... var setActivePage = function() { this.setState({ page: 'active'}); }.bind(this); var setCompletedPage = function() { this.setState({ page: 'completed' }); }.bind(this); var router = Router({ '/active': setActivePage, '/completed': setCompletedPage, '*': setActivePage, }); router.init(); }, render: function() { var page = this.state.page === 'active' ? <TodoList todos={this.state.todos}/> : <div>Completed todos comes here!</div>;//TODO replace with <CompletedTodoList> return ( <div> <h1>My Todo</h1> <ul> <li><a href="#/active">Active</a></li> <li><a href="#/completed">Completed</a></li> </ul> {page} </div> ); } });
/active
と/completed
への遷移(実際にはハッシュが付く)を検知してthis.state
を更新し、それぞれの内容をレンダリングします。デフォルトでは/active
と同じページが表示されるようにしています。
これで画面遷移を実現することができました。あとは、上でTODOになっているコンポーネントを実装すれば完了です。次ページからは、React.jsを使って開発をする上で役立つTipsを紹介します。