[解決済み] クライアントルーティング(react-router使用)およびサーバーサイドルーティング
質問
クライアントとサーバーの間のルーティングについて考えているのですが、混乱しています。サーバーサイドのレンダリングにReactJSを使用してからWebブラウザにリクエストを返し、クライアントサイドのルーティングとしてreact-routerを使用してSPAとして更新せずにページを切り替えたとします。
思い浮かぶのは
-
ルートはどのように解釈されるのでしょうか?例えば、トップページからのリクエスト (
/home
) から Posts ページ (/posts
) - ルーティングはサーバーサイドかクライアントか、どちらで行うのでしょうか?
- どのように処理されるかを知るには?
どのように解決するのですか?
この回答はReact Routerバージョン0.13.xを対象としていることに注意してください。 次期バージョン1.0 は大幅に異なる実装を持つように見えます。
サーバー
これは、最小限の
server.js
をreact-routerで表示しています。
var express = require('express')
var React = require('react')
var Router = require('react-router')
var routes = require('./routes')
var app = express()
// ...express config...
app.use(function(req, res, next) {
var router = Router.create({location: req.url, routes: routes})
router.run(function(Handler, state) {
var html = React.renderToString(<Handler/>)
return res.render('react_page', {html: html})
})
})
ここで
routes
モジュールはRoutesのリストをエクスポートします。
var React = require('react')
var {DefaultRoute, NotFoundRoute, Route} = require('react-router')
module.exports = [
<Route path="/" handler={require('./components/App')}>
{/* ... */}
</Route>
]
サーバへのリクエストが行われるたびに、一回だけ使用する
Router
インスタンスを作成します。これは適切なマッチしたルートをセットアップするためにルートツリーに対して解決され、レンダリングされるトップレベルのルートハンドラと各レベルでマッチした子ルートの記録とともにコールバックされます。これは
<RouteHandler>
コンポーネントを使用して、マッチした子ルートをレンダリングするときに参照されます。
ユーザーが JavaScript をオフにしているか、読み込みに時間がかかっている場合、ユーザーがクリックしたリンクが再びサーバーにヒットし、上記のように再び解決されます。
クライアント
これは最小限の
client.js
をreact-router(同じroutesモジュールを再利用)で実装しています。
var React = require('react')
var Router = require('react-router')
var routes = require('./routes')
Router.run(routes, Router.HistoryLocation, function(Handler, state) {
React.render(<Handler/>, document.body)
})
を呼び出すと
Router.run()
を呼び出すと、舞台裏であなたのために Router インスタンスが作成されます。これは、1 つのリクエストが固定 URL であるサーバー上とは対照的に、クライアント上では URL が動的であり得るため、あなたがアプリ内を移動するたびに再利用されます。
この例では
HistoryLocation
を使用していますが、これは
History
API
を使用して、戻る/進むボタンを押したときに正しい処理が行われるようにします。また
HashLocation
があり、これは URL を変更する
hash
を変更して履歴のエントリを作成し
window.onhashchange
イベントをリスンしてナビゲーションをトリガーします。
react-routerの
<Link>
コンポーネントを使用する場合、このコンポーネントには
to
プロップを与えます。これはルートの名前であり、さらに任意の
params
と
query
のデータが必要です。その
<a>
このコンポーネントによってレンダリングされた
onClick
ハンドラを持ち、最終的に
router.transitionTo()
を呼び出すことになります。
/**
* Transitions to the URL specified in the arguments by pushing
* a new URL onto the history stack.
*/
transitionTo: function (to, params, query) {
var path = this.makePath(to, params, query);
if (pendingTransition) {
// Replace so pending location does not stay in history.
location.replace(path);
} else {
location.push(path);
}
},
通常のリンクの場合、これは最終的に
location.push()
を呼び出します。これは、戻るボタンや進むボタンで移動できるように履歴を設定する詳細を処理し、その後
router.handleLocationChange()
にコールバックして、ルーターに新しい URL パスへの移行を進めることができることを知らせます。
次にルーターは自身の
router.dispatch()
メソッドを呼び出します。このメソッドは、設定されたルートのどれが URL にマッチするかを決定する詳細を処理し、次にすべての
遷移フック
を呼び出します。これらの遷移フックを任意のルート ハンドラに実装して、ルートがナビゲートされなくなるか、またはナビゲートされるときに何らかのアクションを実行し、好みに合わない場合は遷移を中断することができます。
遷移が中止されなかった場合、最後のステップは
Router.run()
に与えたコールバックを、トップレベルのハンドラ コンポーネントと、URL とマッチしたルートのすべての詳細を含むステート オブジェクトとともに呼び出すことです。トップレベルのハンドラ コンポーネントは、実際には
Router
インスタンスそのものであり、マッチした最上位のルートハンドラのレンダリングを扱います。
上記の処理は、クライアントで新しい URL に移動するたびに再実行されます。
プロジェクト例
関連
-
[解決済み] let "と "var "の使い分けは?
-
[解決済み] Reactルータを使ったプログラムによるナビゲーション
-
[解決済み] React-routerのURLを更新したり、手動で書き込んだりするとうまくいかない
-
[解決済み] React NativeとReactの違いは何ですか?
-
[解決済み] クライアントサイドとサーバーサイドのプログラミングの違いは何ですか?
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] JavaScriptで、ある文字列が別の文字列の中に出現するすべてのインデックスを見つけるにはどうすればよいですか?
-
[解決済み] JavaScriptを使用してHTML要素に属性を追加/更新するには?
-
[解決済み] Javascript 空の配列の削減
-
[解決済み] querySelectorAllがない場合、ライブラリを使用せずに属性で要素を取得する?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] <Enter>でjQuery UIダイアログを送信する
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] モバイルWeb HTML5フレームワークの選び方【終了しました
-
[解決済み] javascript の関数から `undefined` と `null` のどちらを返すのが良いのでしょうか?
-
[解決済み] CORS OriginヘッダーとCSRFトークンによるCSRF保護
-
[解決済み] 文字列がhtmlであるかどうかをチェックする
-
[解決済み] jqueryはjavascriptのライブラリなのかフレームワークなのか?[クローズド]
-
[解決済み] イテレータでmap()を使用する
-
[解決済み] Fetch: ステータスがOKでない場合、プロミスを拒否し、エラーをキャッチするか?