[解決済み] React-routerのURLを更新したり、手動で書き込んだりするとうまくいかない
質問
React-routerを使用していますが、リンクボタンをクリックしている間は正常に動作しますが、ウェブページを更新すると、私が望むものが読み込まれません。
例えば、私は
localhost/joblist
というのも、私はリンクを押してここにたどり着いたので、すべてがうまくいっているのです。しかし、私がウェブページを更新した場合、私は取得します。
Cannot GET /joblist
デフォルトでは、このように動作しませんでした。当初、私は自分のURLを
localhost/#/
と
localhost/#/joblist
で、それらは全く問題なく動作しました。しかし、私はこのようなURLは好きではないので、それを消そうとすると
#
, と書きました。
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
ではこの問題は起こりません。
localhost/
これは常に私が望むものを返します。
EDITです。
このアプリはシングルページなので
/joblist
は、どのサーバーにも何も要求する必要がありません。
EDIT2です。 私のルーター全体
var routes = (
<Route name="app" path="/" handler={App}>
<Route name="joblist" path="/joblist" handler={JobList}/>
<DefaultRoute handler={Dashboard}/>
<NotFoundRoute handler={NotFound}/>
</Route>
);
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
解決方法は?
<サブ 受理された回答へのコメントとこの質問の一般的な性質(「うまくいかない」)を見て、私はここがこの問題に関連するいくつかの一般的な説明をするのに良い場所かもしれないと思いました。そこで、この回答は、OPの特定の使用例に関する背景情報/解説を意図しています。どうかご容赦ください。
サーバーサイドとクライアントサイド
まず最初に理解すべきことは、「昔」はURLが1つしか解釈されなかったのに対し、現在は2つの場所で解釈されるようになったということです。昔、生活がシンプルだった頃、あるユーザーがリクエストを送ると
http://example.com/about
サーバーはURLのパス部分を検査し、ユーザーがアバウトページを要求していると判断し、そのページを送り返したのです。
React-Routerが提供するクライアントサイドルーティングの場合、物事はそれほど単純ではありません。最初は、クライアントはまだJSコードを読み込んでいません。そのため、最初のリクエストは常にサーバーに送られます。そして、ReactやReact Routerなどを読み込むために必要なスクリプトタグを含むページを返します。これらのスクリプトがロードされて初めて、フェーズ2が開始されます。フェーズ2では、たとえば、ユーザーが「会社案内」のナビゲーション リンクをクリックすると、URLが変更されます。
ローカルのみ
から
http://example.com/about
(によって実現される)。
履歴API
) が
サーバーへのリクエストは行われません
. その代わり、React Routerがクライアントサイドで処理を行い、どのReactビューをレンダリングするかを決定し、レンダリングします。あなたのaboutページがRESTコールをする必要がないと仮定すると、それはすでに完了しています。サーバーへのリクエストが発生することなく、HomeからAbout Usに遷移したことになります。
つまり、基本的には、リンクをクリックすると、アドレスバーのURLを操作するJavascriptが実行されるわけです。 ページのリフレッシュを行わずに その結果、React Routerがページ遷移を行うことになります。 クライアント側で .
しかし、ここでアドレスバーにURLをコピーペーストして、友人にメールで送信した場合を考えてみましょう。その友人は、まだあなたのウェブサイトを読み込んでいません。つまり、彼女はまだ
フェーズ1
. 彼女のマシンでは、まだReact Routerは実行されていません。そのため、彼女のブラウザは
サーバーリクエスト
に対して
http://example.com/about
.
そして、ここからがトラブルの始まりです。今までは、静的なHTMLをサーバーのwebrootに置くだけで済んでいたのですが、これからは、静的なHTMLをサーバーのwebrootに置くだけでは済まなくなります。しかし、これでは
404
は、他のすべてのURLに対してのエラー
サーバから要求されたとき
. 同じURLは問題なく動作します
クライアント側で
React Router がルーティングを行うからです。しかし、以下のように失敗します。
サーバーサイドで
サーバーに理解させない限り。
サーバーサイドとクライアントサイドのルーティングを組み合わせる
もし
http://example.com/about
の URL をサーバー側とクライアント側の両方で動作させるには、サーバー側とクライアント側の両方でそのためのルートを設定する必要があります。理にかなっていますよね?
そして、ここからが選択のしどころです。ブートストラップ HTML を返すキャッチオールルートによって問題を完全に回避する方法から、サーバーとクライアントの両方で同じ JS コードを実行する完全なアイソモーフィックアプローチまで、さまざまな解決策があります。
問題を完全に回避する ハッシュ履歴
と
ハッシュ履歴
の代わりに
ブラウザの履歴
の場合、aboutページのURLは次のようになります。
http://example.com/#/about
ハッシュの後の部分(
#
) の記号はサーバーに送信されません。そのため、サーバーが見るのは
http://example.com/
で、期待通りにインデックスページを送信します。React-Router は
#/about
の部分を削除し、正しいページを表示します。
デメリット :
- 醜い」URL
- この方法では、サーバーサイドレンダリングは不可能です。検索エンジン最適化(SEO)に関して言えば、あなたのウェブサイトは、ほとんどコンテンツのない1つのページで構成されているのです。
キャッチオール
この方法では、ブラウザの履歴を使用しますが、サーバー上にキャッチオールを設定して
/*
から
index.html
となり、事実上Hash Historyと同じ状況になります。しかし、きれいなURLは確保されており、ユーザーのお気に入りをすべて無効にすることなく、この方式を後で改良することができます。
デメリット :
- セットアップがより複雑
- SEO対策はまだ不十分
ハイブリッド
ハイブリッド・アプローチでは、特定の経路に特定のスクリプトを追加することで、キャッチオール・シナリオを拡張することができます。シンプルなPHPスクリプトをいくつか作成して、サイトの最も重要なページをコンテンツ付きで返すようにすれば、Googlebotは少なくともあなたのページに何があるのかを見ることができます。
デメリット :
- さらに複雑なセットアップ
- 特別扱いしたルートのみSEO効果がある
- サーバーとクライアントでコンテンツをレンダリングするためのコードが重複している
アイソモフィック
Node JSをサーバーとして使用し、以下のように実行することができます。 同じ JSのコードが両端にある?これで、すべてのルートが1つのreact-routerの設定に定義され、レンダリングコードを重複させる必要がなくなりました。これは、いわば「聖杯」です。ページ遷移がクライアントで発生した場合と全く同じマークアップがサーバーから送信されます。このソリューションは、SEOの観点からも最適です。
デメリット :
- サーバー 必須 (JSを実行できる)。Java i.c.w. Nashornで実験してみたが、私にはうまくいかない。実際には、Node JSベースのサーバーを使用する必要があることがほとんどです。
-
多くの厄介な環境問題(
window
サーバーサイドなど) - 学習曲線が急峻
どれを使えばいいのか?
自分が納得できるものを選びましょう。個人的にはキャッチオールがシンプルで設定しやすいと思うので、それが最低ラインでしょう。この設定であれば、時間をかけていろいろと改良していくことができます。もし、サーバープラットフォームとしてすでにNode JSを使っているなら、ぜひアイソモーフィック・アプリをやってみることを検討します。確かに最初は大変ですが、一度コツをつかめば、実はとてもエレガントな問題解決法なのです。
だから基本的には、私にとってはそれが決め手になりますね。そうでない場合は、キャッチオール・ソリューションを採用し、時間の経過とSEOの要求に応じて(ハイブリッド・ソリューションを)拡張していくことになるでしょう。
Reactのisomorphic(ユニバーサル)レンダリングについてもっと知りたい方は、このテーマに関する良いチュートリアルがいくつかあります。
また、スタートアップのために、いくつかのスターターキットを見ることをお勧めします。技術スタックの選択肢にマッチするものを選んでください(ReactはMVCのVに過ぎず、完全なアプリを構築するにはもっと多くのものが必要であることを忘れないでください)。まずは、Facebookが公開しているものを見てみてください。
または、コミュニティによる多くのものの中から1つを選びます。現在では、それらすべてをインデックス化しようとする素晴らしいサイトがあります。
私はこれらから始めました。
現在、私は上記の2つのスターターキットに触発された自作版のユニバーサルレンダリングを使用していますが、それらはもう古くなっています。
頑張ってください
関連
-
vue3レスポンシブ対応のためのsetup+ref+reactive
-
親子コンポーネント通信を解決する3つのVueスロット
-
Vueがechartsのtooltipにクリックイベントを追加するケーススタディ
-
JavaScriptの配列共通メソッド解説
-
[解決済み] TypeError: $.ajax(...) is not a function?
-
[解決済み] Reactルータを使ったプログラムによるナビゲーション
-
[解決済み] セルフクローズスクリプトエレメントが機能しないのはなぜですか?
-
[解決済み] React Router v4で履歴にプッシュする方法は?
-
[解決済み] react-router - ハンドラコンポーネントにpropsを渡す
-
[解決済み】オプションのパスパラメータを持つReact Router
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
Vueの要素ツリーコントロールに破線を追加する説明
-
jsを使った簡単な照明スイッチのコード
-
元のイベントが実行されなかった後に要素を追加するためのjQueryソリューション
-
vue+webrtc(Tencent cloud)ライブ機能の実践を実現するために
-
Vueのクラススタイルの使い方の詳細
-
Vueのフォームイベントのデータバインディングの説明
-
[解決済み] 配列の結合時に未定義のプロパティ 'push' を読み込むことができない
-
[解決済み】エラー。Ionic使用中にモジュール '../lib/utils/unsupported.js' が見つかりませんでした。
-
フロントエンド非同期(アシンク)ソリューション(全ソリューション)
-
JSクリックイベント - Uncaught TypeError: プロパティ 'onclick' に null を設定できません。