私はReact-routerを使用していて、リンクボタンをクリックしている間はうまく機能していますが、Webページを更新しても必要なものが読み込まれません。
例えば、私はlocalhost/joblist
にいます、そして私がリンクを押すことでここに到着したので、すべてが大丈夫です。しかし、Webページを更新すると、次のようになります。
Cannot GET /joblist
デフォルトでは、これはうまくいきませんでした。当初、私のURLはlocalhost/#/
とlocalhost/#/joblist
としていましたが、それらは完全にうまく機能しました。しかし、私はこの種のURLが好きではないので、その#
を消そうとして、私は書いた:
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
この問題はlocalhost/
では起こりません、これは私が欲しいものを常に返します。
編集: このアプリはシングルページなので、/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が解釈される場所が2つあるのに対し、「昔」には1つしかなかったことです。以前は、生活が単純だったときに、一部のユーザーがhttp://example.com/about
のリクエストをサーバーに送信し、URLのパス部分を検査し、ユーザーがAboutページをリクエストしていると判断し、そのページを送り返しました。
React-Routerが提供するクライアント側ルーティングでは、物事はそれほど単純ではありません。最初は、クライアントにはJSコードがまだロードされていません。そのため、最初の要求は常にサーバーに対して行われます。その後、ReactやReact Routerなどをロードするために必要なスクリプトタグを含むページが返されます。これらのスクリプトがロードされた場合にのみ、フェーズ2が開始します。フェーズ2では、ユーザーが「About us」ナビゲーションリンクをクリックすると、URLが変更されますローカルのみからhttp://example.com/about
( History API)によって可能になります )、ただしサーバーへの要求は行われません。代わりに、React Routerはクライアント側で処理を行い、どのReactビューをレンダリングするかを決定してレンダリングします。 aboutページがREST呼び出しを行う必要がないと仮定すると、既に完了しています。サーバーリクエストが発生することなく、HomeからAbout Usに移行しました。
したがって、基本的にリンクをクリックすると、アドレスバーのURLを操作するJavascriptが実行されます[ページの更新を行わない。これにより、Reactルーターがページ遷移を実行します。 クライアント側。
ただし、アドレスバーにURLをコピーして貼り付け、友人に電子メールで送信するとどうなるかを考えてみましょう。あなたの友人はあなたのウェブサイトをまだロードしていません。つまり、彼女はまだphase 1にいます。いいえReactルーターはまだマシン上で実行されていません。そのため、彼女のブラウザはhttp://example.com/about
に対してサーバー要求を行います。
そして、ここからトラブルが始まります。今までは、サーバーのwebrootに静的なHTMLを配置するだけで済みました。しかし、それは他のすべてのURLに対して404
エラーを与えますサーバーから要求されたとき。これらの同じURLは正常に機能しますクライアント側で、なぜならReactルーターがあなたのためにルーティングを行っていますが、失敗しますサーバー側でサーバーにそれらを理解させる。
http://example.com/about
URLをサーバー側とクライアント側の両方で機能させる場合は、サーバー側とクライアント側の両方でそのルートを設定する必要があります。理にかなっていますか?
そして、ここから選択が始まります。解決策は、bootstrap HTMLを返すキャッチオールルートを介した問題のバイパスから、サーバーとクライアントの両方が同じJSコードを実行する完全同形アプローチにまで及びます。
。
ブラウザ履歴 ではなく ハッシュ履歴 を使用すると、aboutページのURLは次のようになります。http://example.com/#/about
ハッシュの後の部分(#
)シンボルはサーバーに送信されません。したがって、サーバーはhttp://example.com/
のみを認識し、期待どおりにインデックスページを送信します。 React-Routerは#/about
部分を選択し、正しいページを表示します。
欠点:
。
このアプローチでは、ブラウザ履歴を使用しますが、/*
をindex.html
に送信するサーバー上でキャッチオールを設定するだけで、ハッシュ履歴とほぼ同じ状況を効果的に提供します。ただし、クリーンなURLがあり、ユーザーのお気に入りをすべて無効にすることなく、後でこのスキームを改善できます。
欠点:
。
ハイブリッドアプローチでは、特定のルートに特定のスクリプトを追加することにより、キャッチオールシナリオを拡張します。簡単なPHPスクリプトを作成して、コンテンツを含むサイトの最も重要なページを返すことができるため、Googlebotは少なくともページの内容を確認できます。
欠点:
。
Node JSをサーバーとして使用して、両端で同じ JSコードを実行できるとしたらどうでしょうか。これで、すべてのルートが単一の反応ルーター構成で定義され、レンダリングコードを複製する必要がなくなりました。これはいわば「聖杯」です。サーバーは、クライアントでページの遷移が発生した場合に最終的に同じマークアップを送信します。このソリューションは、SEOの観点から最適です。
欠点:
window
を使用)。
あなたが逃げることができるものを選択してください。個人的には、キャッチオールはセットアップするのに十分簡単であると思うので、それが私の最小になるでしょう。この設定により、時間の経過とともに改善することができます。サーバープラットフォームとして既にNode JSを使用している場合、同形アプリの実行を確実に調査します。はい、それは最初は難しいですが、一度それを理解したら、それは実際には問題に対する非常にエレガントな解決策です。
基本的に、私にとっては、それが決定的な要因になります。サーバーがNode JSで実行されている場合、同形になります。それ以外の場合は、キャッチオールソリューションに進み、時間の経過とSEO要件に応じて、それを拡張します(ハイブリッドソリューション)。
Reactによる同形(「ユニバーサル」とも呼ばれる)レンダリングの詳細については、このテーマに関するいくつかの優れたチュートリアルがあります。
また、開始するには、スターターキットをご覧になることをお勧めします。テクノロジースタックの選択に一致するものを1つ選択します(ReactはMVCの単なるVであり、完全なアプリを構築するにはさらに多くのものが必要です)。 Facebook自体が公開しているものを見てみましょう。
または、コミュニティの多くのいずれかを選択します。すべてのインデックスを作成しようとするニースのサイトがあります:
私はこれらから始めました:
現在、私は上記の2つのスターターキットに触発された自作のユニバーサルレンダリングバージョンを使用していますが、現在は古くなっています。
あなたの探求で頑張ってください!
ここでの答えはすべて非常に役に立ちます。私にとって効果的だったのは、Webpackサーバーを経路を予想するように構成することでした。
devServer: {
historyApiFallback: true,
contentBase: './',
hot: true
},
HistoryApiFallbackは、この問題を解決したものです。これでルーティングは正しく機能し、ページを更新したりURLを直接入力することができます。ノードサーバーの回避策について心配する必要はありません。この答えは明らかにwebpackを使用している場合にのみ有効です。
編集:これが必要である理由の詳細な理由については私の答えをここに見てください: https://stackoverflow.com/a/37622953/5217568
React Router V4 Usersの場合:
あなたが他の答えで言及されたハッシュ履歴技術によってこの問題を解決しようとするならば、それに注意してください
<Router history={hashHistory} >
v4では動作しません。代わりにHashRouter
を使用してください。
import { HashRouter } from 'react-router-dom'
<HashRouter>
<App/>
</HashRouter>
参照: https://reacttraining.com/react-router/web/api/HashRouter
あなたのhtaccessを変更してこれを挿入することができます:
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
私はreact: "^15.3.2"
、react-router: "^3.0.0"
、history: "^4.3.0"
を使っています、
ナビゲーションは、クライアント上で行われるのか、サーバー上で行われるのかに応じて、2つの異なる方法で呼び出すことができます。クライアント側の操作用に設定しました。重要なパラメータは、 runメソッド の2番目の場所です。
React Router Linkコンポーネントを使用すると、ブラウザのナビゲーションがブロックされ、transitionToが呼び出されてクライアントサイドのナビゲーションが行われます。 HistoryLocationを使用しているので、アドレスバーの新しいURLをシミュレートすることによってナビゲーションの錯覚を完成させるためにHTML5履歴APIを使用します。古いブラウザを使用している場合、これは機能しません。 HashLocationコンポーネントを使う必要があるでしょう。
Refreshを押すと、ReactコードとReact Routerコードをすべて回避します。サーバーは/joblist
の要求を受け取り、それは何かを返さなければなりません。サーバーでは、正しいビューをレンダリングするために、要求されたパスをrun
メソッドに渡す必要があります。同じルートマップを使用できますが、おそらくRouter.run
への別の呼び出しが必要になります。 Charlesが指摘したように、あなたはこれを処理するためにURL書き換えを使うことができます。もう1つの選択肢は、node.jsサーバーを使用してすべての要求を処理し、パスの値をlocation引数として渡すことです。
たとえば、エクスプレスでは、次のようになります。
var app = express();
app.get('*', function (req, res) { // This wildcard method handles all requests
Router.run(routes, req.path, function (Handler, state) {
var element = React.createElement(Handler);
var html = React.renderToString(element);
res.render('main', { content: html });
});
});
要求パスがrun
に渡されていることに注意してください。これを行うには、レンダリングされたHTMLを渡すことができるサーバーサイドビューエンジンが必要です。 renderToString
を使用したり、サーバー上でReactを実行する際には、他にもいくつか考慮事項があります。ページがサーバーにレンダリングされると、アプリケーションがクライアントにロードされると、再度レンダリングされ、必要に応じてサーバーサイドにレンダリングされたHTMLが更新されます。
Index.html head
に、以下を追加します。
<base href="/">
<!-- This must come before the css and javascripts -->
それから、webpack dev serverで実行しているときは、このコマンドを使用してください。
webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback
--history-api-fallback
は重要な部分です
Webpack Dev Serverにはこれを有効にするオプションがあります。 package.json
を開き、--history-api-fallback
を追加します。この解決策は私のために働いた。
AWS Static S3 Hosting&CloudFrontを介して反応型アプリをホストしている場合
この問題は、/ some/other /パスがS3フォルダに存在することを想定していたため、CloudFrontが403 Access Deniedメッセージで応答していましたが、そのパスはReactのreact-routerによるルーティングに内部的にのみ存在します。
解決策は、配布エラーページルールを設定することでした。 CloudFrontの設定に行き、あなたのディストリビューションを選択してください。次に「エラーページ」タブに行きます。 「Create Custom Error Response」をクリックして403のエントリを追加します。これがエラーステータスコードです。応答ページのパスを/index.htmlに、ステータスコードを200に設定します。その結果、その単純さに驚かされます。インデックスページは提供されますが、URLはブラウザに保存されるため、反応アプリケーションがロードされると、URLパスが検出され、目的のルートに移動します。
これはあなたの問題を解決することができます
プロダクションモードのReactJSアプリケーションでも同じ問題に直面しました。これが問題の2つの解決策です。
1.ルーティング履歴を、代わりにbrowserHistoryの代わりに "hashHistory"に変更します。
<Router history={hashHistory} >
<Route path="/home" component={Home} />
<Route path="/aboutus" component={AboutUs} />
</Router>
今コマンドを使用してアプリを構築します
Sudo npm run build
それから、buildフォルダをあなたのvar/www /フォルダに置いてください。これでアプリケーションはそれぞれのURLに#タグを追加してうまく動作しています。好き
localhost /#/ home localhost /#/ aboutus
解決策2:browserHistoryを使用して#タグを付けずに
あなたのルーターであなたのhistory = {browserHistory}を設定してください、今Sudo npm run buildを使ってそれを構築してください。
404見つからないページを解決するには、 "conf"ファイルを作成する必要があります。confファイルは次のようになります。
以下のコマンドを入力して端末を開きます。
cd/etc/Apache2/sites-available ls nano sample.conf次の内容を追加してください。
<VirtualHost *:80>
ServerAdmin [email protected]
ServerName 0.0.0.0
ServerAlias 0.0.0.0
DocumentRoot /var/www/html/
ErrorLog ${Apache_LOG_DIR}/error.log
CustomLog ${Apache_LOG_DIR}/access.log combined
<Directory "/var/www/html/">
Options Indexes FollowSymLinks
AllowOverride all
Require all granted
</Directory>
</VirtualHost>
次のコマンドを使用してsample.confファイルを有効にする必要があります。
cd /etc/Apache2/sites-available
Sudo a2ensite sample.conf
それから、SudoサービスApache2 reloadまたはrestartを使用して、Apacheサーバーをリロードするように求められます。
次にlocalhost/buildフォルダを開き、以下の内容の.htaccessファイルを追加します。
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ / [L,QSA]
これでアプリは正常に動作しています。
注:0.0.0.0 ipをローカルIPアドレスに変更します。
これについて疑問がある場合は、コメントをお願いします。
私はそれが他の人に役立つことを願っています。
私はちょうど今ウェブサイトを作成するためにcreate-react-appを使用し、ここに提示された同じ問題を抱えていました。 react-router-dom
パッケージのBrowserRouting
を使います。私はNginxサーバー上で実行していて、それを解決したのは/etc/nginx/yourconfig.conf
に以下を追加することでした
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /index.html break;
}
}
Appacheを実行している場合、これは.htaccess
に以下を追加することに対応します
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
これもFacebook自身が提案した解決策のようであり、見つけることができます ここ
プロダクションスタック:React、React Router v4、BrowswerRouter、Express、Nginx
1)可愛いURL用のUser BrowserRouter
// app.js
import { BrowserRouter as Router } from 'react-router-dom'
const App = () {
render() {
return (
<Router>
// your routes here
</Router>
)
}
}
2)/*
を使用して、すべての未知の要求にindex.htmlを追加します。
// server.js
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
})
3)webpack -p
を含むwebpackをバンドルする
4)nodemon server.js
またはnode server.js
を実行する
編集:あなたはnginxにサーバブロックでこれを処理させて、ステップ2を無視させることを望むかもしれません:
location / {
try_files $uri /index.html;
}
これをwebpack.config.jsに追加してください。
devServer: {
historyApiFallback: true
}
以下のコードでパブリックフォルダ内に ".htaccess"ファイルを追加してみてください。
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html [L]
Create React Appを使用している場合:
この問題については、Create React Appページで _ here _ を参照してください。たとえば、フロントエンドコードにはReact Router v4とNetlifyを使用します。必要なのは、私のパブリックフォルダ( "_redirects")に1つのファイルを追加し、そのファイルに1行のコードを追加することだけでした。
/* /index.html 200
今すぐ私のウェブサイトは正しくブラウザに入力したときや誰かがリフレッシュを押したときにmysite.com/pricingのようなパスをレンダリングします。
このトピックは少し古く、解決されていますが、私はあなたに単純明快でより良い解決策を提案したいと思います。 Webサーバーを使用している場合は機能します。
各Webサーバーには、http 404の場合にユーザーをエラーページにリダイレクトする機能があります。この問題を解決するには、ユーザーをインデックスページにリダイレクトする必要があります。
Javaベースサーバー(Tomcatまたは任意のJavaアプリケーションサーバー)を使用している場合、解決策は次のようになります。
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- WELCOME FILE LIST -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- ERROR PAGES DEFINITION -->
<error-page>
<error-code>404</error-code>
<location>/index.jsp</location>
</error-page>
</web-app>
例:
それはそれです、もう魔法の必要はありません:)
Index.htmlにフォールバックする場合は、index.htmlファイルに次のように記述してください。
<script>
System.config({ baseURL: '/' });
</script>
これはプロジェクトによって異なります。
IIS上でReactアプリケーションをホストしている場合は、次のものを含むweb.configファイルを追加するだけです。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
</configuration>
これはIIS serverに404エラーの代わりにメインページをクライアントに返すように指示し、ハッシュ履歴を使う必要はありません。
Firebaseを使用している場合は、アプリのルート(ホスティングセクション)にあるfirebase.jsonファイルにrewritesプロパティがあることを確認するだけです。
例えば:
{
"hosting": {
"rewrites": [{
"source":"**",
"destination": "/index.html"
}]
}
}
これが他の誰かにフラストレーションの溜まりと時間の無駄を省くことを願っています。
ハッピーコーディング...
件名についてさらに読む:
https://firebase.google.com/docs/hosting/full-config#rewrites
Firebase CLI: "シングルページアプリとして設定する(すべてのURLを/index.htmlに書き換え)" /
私はまだサーバーサイドレンダリングを使っていませんが、Linkはほとんどの場合うまく機能しているように見えますが、パラメータがあると失敗するというOPと同じ問題に遭遇しました。私は自分の解決策をここで文書化して、誰かに役立つかどうかを確認します。
私のメインのjsxはこれを含みます:
<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />
これは最初にマッチしたリンクではうまくいきますが、そのモデルの詳細ページにネストされた<Link>
式の中で:idが変わったとき、URLはブラウザバーで変わりますがページのコンテンツはリンクモデルを反映するように変わりません。
問題は、モデルをcomponentDidMount
に設定するためにprops.params.id
を使用していたことです。コンポーネントは一度だけマウントされるため、最初のモデルはページに固定され、それ以降のリンクは小道具を変更しますが、ページは変更されずにそのまま残ります。
componentDidMount
とcomponentWillReceiveProps
(次の小道具に基づいています)の両方でモデルをコンポーネント状態に設定すると、問題が解決し、ページの内容が目的のモデルを反映するように変更されます。
.Net Core MVCを使用しているので、このようなことが役に立ちました。
public class HomeController : Controller
{
public IActionResult Index()
{
var url = Request.Path + Request.QueryString;
return App(url);
}
[Route("App")]
public IActionResult App(string url)
{
return View("/wwwroot/app/build/index.html");
}
}
基本的にMVC側では、Home/Index
で指定されているように、一致しないすべての経路はstartup.cs
に分類されます。 Index
の中で、元のリクエストのURLを取得し、必要な場所に渡すことができます。
startup.cs
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
IISでホスティングしている場合私のwebconfigにこれを追加することは私の問題を解決しました
<httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
<remove statusCode="500" subStatusCode="100" />
<remove statusCode="500" subStatusCode="-1" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/" responseMode="ExecuteURL" />
<error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
<error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
</httpErrors>
他のサーバーでも同様の設定ができます
万が一の場合、誰でもLaravelを使ったReact JS SPAの解決策を探しています。 受け入れられた答えは、そのような問題が起こる理由の最も良い説明です。すでに説明したように、クライアント側とサーバー側の両方を構成する必要があります。あなたのブレードテンプレートにjsバンドルファイルを含めて、URL facade
を必ずこのように使用してください。
<script src="{{ URL::to('js/user/spa.js') }}"></script>
ルートで、ブレードテンプレートがあるメインエンドポイントにこれを追加してください。例えば、
Route::get('/setting-alerts', function () {
return view('user.set-alerts');
});
上記がブレードテンプレートの主要エンドポイントです。今度はオプションのルートも追加します。
Route::get('/setting-alerts/{spa?}', function () {
return view('user.set-alerts');
});
発生する問題は、最初にブレードテンプレートがロードされ、次に反応ルータがロードされることです。そのため、'/setting-alerts'
をロードすると、htmlとjsがロードされます。しかし'/setting-alerts/about'
をロードすると、最初にサーバー側でロードされます。サーバー側では、この場所には何もないので、見つかりません。あなたがそのオプションのルータを持っているとき、それはその同じページをロードし、反応ルータもロードされ、そして反応ローダはどのコンポーネントを表示するかを決定します。お役に立てれば。
バックエンドでExpressや他のフレームワークを使用している場合は、以下のように同様の設定を追加してWebpackのパブリックパスをチェックアウトすることができます。
` expressApp.get('/*', (request, response) => {
response.sendFile(path.join(__dirname, '../public/index.html'));
});`
私は反応ルータ(アパッチ)と私のSPAのための解決策を見つけました。 .htaccessを追加するだけです
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . /index.html [L]
</IfModule>
ソース: https://Gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042
Joshua Dyckの答えにもっと情報を追加してください 。
Firebaseを使用していて、ルートルートとサブディレクトリルートの両方を使用したい場合は、firebase.json
に次のコードを追加する必要があります。
{
"hosting": {
"rewrites": [
{
"source": "*",
"destination": "/index.html"
},
{
"source": "/subdirectory/**",
"destination": "/subdirectory/index.html"
}
]
}
}
例:
あなたはクライアントのためのウェブサイトを構築しています。 Webサイトの所有者は https://your.domain.com/management に情報を追加し、Webサイトのユーザーは https://your.domain.com に移動します。
この場合、あなたのfirebase.json
ファイルは以下のようになります。
{
"hosting": {
"rewrites": [
{
"source": "*",
"destination": "/index.html"
},
{
"source": "/management/**",
"destination": "/management/index.html"
}
]
}
}
これは、サーバー上で何も変更する必要がないことを発見したフロントエンドの回避策です。
あなたのサイトがmysite.comであり、mysite.com/aboutへのReact Routeがあるとします。トップレベルコンポーネントをマウントするindex.jsでは、次のような別のルーターを配置できます。
ReactDOM.render(
<Router>
<div>
<Route exact path="/" component={Home} />
<Route exact path="/about"
render={(props) => <Home {...props} refreshRout={"/about"}/>}
/>
</div>
</Router>,
仮想DOMの最上位コンポーネントの下のどこかに元のルーターがあると仮定しています。 Djangoを使用している場合は、.urlsでURLをキャッチする必要もあります。
urlpatterns = [
path('about/', views.index),
]
ただし、これは使用しているバックエンドによって異なります。 mysite/aboutをリクエストすると、index.js(トップレベルコンポーネントをマウントする場所)に移動し、そこでコンポーネントのプロップではなく、ルートのレンダープロップを使用し、「/ about」をプロップとして渡すことができます。この例は、ホームコンポーネントです。
Home内で、componentDidMount()またはuseEffect()フックのいずれかで、以下を実行します。
useEffect() {
//check that this.props.refreshRoute actually exists before executing the
//following line
this.props.history.replace(this.props.refreshRoute);
}
ホームコンポーネントが次のようなものをレンダリングしていると仮定しました。
<Router>
<Route exact path="/" component={SomeComponent} />
<Route path="/about" component={AboutComponent} />
</Router>
Routes内のコンポーネントに小道具を渡す方法については、( React Routerによってレンダリングされたコンポーネントに小道具を渡す )に感謝します。
例付きの完全なルーター (React Router v4):
サンプル作業例以下のプロジェクトをチェックしてください。
https://github.com/eh3rrera/react-router-4-example
ダウンロード後
1)プロジェクトをインストールするためのcmdの "npm install"
2。) "npm start"をクリックしてあなたの反応アプリを起動します。
注:あなたのウィンドウで実行するにはNode jsソフトウェアが必要です。 Mac OSにはノードデフォルトがあります。
乾杯
IIS 10を使用している人にとって、これは正しいことをするためにあなたがすべきことです。これでbrowserHistoryを使用していることを確認してください。参考までに、ルーティングのコードを示しますが、これは重要ではありません。重要なのは、以下のコンポーネントコードの次のステップです。
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<div>
<Root>
<Switch>
<Route exact path={"/"} component={Home} />
<Route path={"/home"} component={Home} />
<Route path={"/createnewproject"} component={CreateNewProject} />
<Route path={"/projects"} component={Projects} />
<Route path="*" component={NotFoundRoute} />
</Switch>
</Root>
</div>
</Router>
)
}
}
render (<App />, window.document.getElementById("app"));
問題はIISがクライアントのブラウザからリクエストを受け取ることであるため、URLをページを要求しているかのように解釈し、利用可能なページがないため404ページを返します。以下をせよ:
そしてそれは今うまくいくでしょう。
助けになれば幸いです。 :-)
私はWebPackを使用しています、私は同じ問題を抱えていましたSolution =>あなたのserver.jsファイルに
const express = require('express');
const app = express();
app.use(express.static(path.resolve(__dirname, '../dist')));
app.get('*', function (req, res) {
res.sendFile(path.resolve(__dirname, '../dist/index.html'));
// res.end();
});
次のホームルート定義があると仮定します
<Route exact path="/" render={routeProps => (
<Home routeProps={routeProps}/>
)}/>
{/*optional catch-all router */}
<Route render={routeProps => (
<div><h4>404 not found</h4></div>
)}/>
ホームコンポーネントでは、ComponentWillMountイベントでリクエストをインターセプトできます。
const searchPath = this.props.routeProps.location.search;
if (searchPath){
this.props.routeProps.history.Push("/" + searchPath.replace("?",""));
}
else{
/*.... originally Home event */
}
これで、urlで/ joblistを呼び出す代わりに、/?joblistを要求できます。コンポーネントは、要求を/ joblistに自動リダイレクトします(パス内の余分な疑問符に注意してください)
あなたがここに来て、Apacheを使用していて、.htaccessファイルを持っていない場合、これは私のために働いた設定ファイルです:
sites-enabled/somedomain.com.conf
<VirtualHost *:80>
ServerName somedomain.com
ServerAlias *.somedomain.com
DocumentRoot /www/somedomain.com/build
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /www/somedomain.com/build/index.html [L,NC,QSA]
</VirtualHost>
私はこれと同じ問題を抱えていたそして これ 解決策は私達のために働いた..
バックグラウンド:
同じサーバー上で複数のアプリをホストしています。サーバーを更新すると、その特定のアプリのdistフォルダーのどこでインデックスを探すべきかがわかりません。上記のリンクは私達のために働いたものにあなたを連れて行くでしょう...私達が私達の必要性のための解決策を考え出すことにかなりの時間を費やしたのでこれが助けてくれることを願っています。
私たちは使っています:
package.json
"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}
私のwebpack.config.js
webpack.config.js
/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
template: __dirname + '/app/views/index.html',
filename: 'index.html',
inject: 'body'
});
module.exports = {
entry: [
'babel-polyfill', './app/index.js'
],
output: {
path: __dirname + '/dist/your_app_name_here',
filename: 'index_bundle.js'
},
module: {
rules: [{
test: /\.js$/,
loader: 'babel-loader',
query : {
presets : ["env", "react", "stage-1"]
},
exclude: /node_modules/
}]
},
plugins: [HTMLWebpackPluginConfig]
}
私のindex.js
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'
const store = configureStore();
const browserHistory = useRouterHistory(createHistory) ({
basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)
persistStore(store, {blacklist: ['routing']}, () => {
console.log('rehydration complete')
})
// persistStore(store).purge()
ReactDOM.render(
<Provider store={store}>
<div>
<Routes history={history} />
</div>
</Provider>,
document.getElementById('mount')
)
私のapp.js
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.get('/*', function (req, res) {
res.render('index');
});
app.listen(8081, function () {
console.log('MD listening on port 8081!');
});
更新時またはURLを直接呼び出す際の「GET/URLができない」エラーを修正しました。
与えられたリンクがこのようなルートになるように webpack.config.js を設定します。
module.exports = {
entry: './app/index.js',
output: {
path: path.join(__dirname, '/bundle'),
filename: 'index_bundle.js',
publicPath: '/'
},
私はそれを扱うこの方法が好きです。この問題を解決するには、サーバー側で: yourSPAPageRoute/* を追加してください。
ネイティブHTML5 History APIでさえページ更新時の正しいリダイレクトをサポートしていないので(私の知る限りでは)このアプローチを採用しました。
注:選択された回答はすでにこれに対処していますが、私はより具体的になろうとしています。
それが役に立てば幸い。
Preact-routerを使用したPreactの解決策
更新と直接アクセスで動作します
Googleでこれを発見した人のために、これはpreact-router +のハッシュ履歴のデモです。
const { h, Component, render } = preact; /** @jsx h */
const { Router } = preactRouter;
const { createHashHistory } = History;
const App = () => (
<div>
<AddressBar />
<Router history={createHashHistory()}>
<div path="/">
<p>
all paths in preact-router are still /normal/urls.
using hash history rewrites them to /#/hash/urls
</p>
Example: <a href="/page2">page 2</a>
</div>
<div path="/page2">
<p>Page Two</p>
<a href="/">back to home</a><br/>
</div>
</Router>
</div>
);
あなたが手に入れたときその非常に単純なリフレッシュDOMコンポーネントの後に403エラーを取得することはできません。 Webパックの設定に 'historyApiFallback:true'という1行を追加するだけです。これで私の一日が節約できます。