React Routerで良く起きる問題! 〜 ページがない!
React Router で良く起きる問題! 〜 ページがない!
React Router を利用すると、React で作成したアプリを複数のページで構成する Web サイトとして構成することができます。しかし、実際に Web サーバーで公開すると「ページがない!」というエラーが発生する場合があります。一体何が起きているのでしょう?
目次 |
---|
React Router は何をしているのか? |
サーバーにはページがない! |
Web サーバーに教える必要があります! |
React Router の設定方法は? |
まとめ |
React Router は何をしているのか?
React Router は一体何をやっているのでしょうか? React Router は、React の拡張機能で、Web ブラウザでページの URL を指定すると、別のページがあるように表示できる機能です。この時、どのページを表示するかを決めているのは実は React が作った、Javascript のコードでページを作っています。
ところが、この処理を普通は Web サーバーが行なっています。通常は、Web サーバーが Web ブラウザが指定された URL をもとに Web サーバーにリクエストを送って、Web サーバーがどの表示するかを決めて Web ブラウザに表示するページを送っています。
このどのページを表示するかを決める処理を「ルーティング」と呼んでいます。
サーバーにはページがない!
React で React Router を使って利用している場合には、React が表示するページを作って、index.htmlに表示させています。つまり、「サーバーにはそのページはない」のでエラーになります。
でも、React の開発用のサーバーを「npm start」で起動して動かすと問題なく動きます。 これは、React の開発用のサーバーは予め React がページのルーティングを行なっている前提の設定になっているために、問題なく動作します。
ところが、通常の Web サーバーの場合は、Web サーバー側でルーティングを行う前提なので、React がページを作っているとは思っていないので、エラーになってしまいます。
Web サーバーに教える必要があります!
この問題を解決するには、Web サーバーに React がルーティングをしていることを予め設定して教えておく必要があります。
Firebase の場合には、プロジェクトフォルダにある「firebase.json」で設定を行います。
{
"hosting": {
"public": "build",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
}
}
「hosting」の設定に、「rewirtes」を加えて、どのようなリクエスが来ても、「index.html」を表示するようにします。これで、ルーティングの処理を全て、React に任せるようになるため、React Router で指定されたページも正常に表示できるようになります。
React Router の設定方法は?
React Router を利用するには、「react-router-dom」をインストールする必要があります。
$ npm install react-router-dom
$ npm install --save-dev @types/react-router-dom
これで、あとは、「App.tsx」の記述を変更します。
import React from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "./pages/home";
import Post from "./pages/post";
import "./App.css";
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/" exact>
<Home />
</Route>
<Route path="/post">
<Post />
</Route>
</Switch>
</BrowserRouter>
);
}
export default App;
これで、二つの「Home」と「Post」のページをそれぞれ「/」と「/post」で表示できるようになります。
(post.tsx)の例 〜 「Post」と表示するだけ!
import * as React from "react";
export default class Post extends React.Component {
render() {
return (
<React.Fragment>
<div>
<h1>Post</h1>
</div>
</React.Fragment>
);
}
}
これで、複数のページを「index.html」に表示できるようになります。
まとめ
React Router を利用すると、複数のページが存在するような感じで Web アプリを構成する事ができます。この設定は、React の開発用のサーバーを利用してテストする場合には問題なく動作します。(「npm start」を使ってテストする場合)
しかし、実際にインターネットに公開するために、公開用のイメージを作成して Web サーバーで公開すると、「ページがない」というエラーになってしまう場合があります。 これは、Web サーバー側の設定がきちんとされていないために起きます。実際にサーバーにはそのページがないので当然エラーになるわけです。
Firebase でホスティングしている場合の設定はシンプルで、firebase.jsonに簡単な記述を追加するだけで動作するようにできます。
これは、プログラミングの問題というより、サーバーの設定の問題ですが、Web ページの「ルーティング」の仕組みがよくわかっていないと設定を忘れてしまう場合があるので注意が必要です!