Reactでルーティングの設定をするためにreact-router-domを使用します。
パッケージを使わずに自分でURLごとに切り出すコードを書いてもいい気もしますが、かなり有名なパッケージですしせっかくなので使ってみます。
ディレクトリ構成とかは違うと思いますが、基本的な使い方自体は簡単なのでうまく読み替えてください。
react-router-domをインストールする
以下のコマンドを実行してreact-router-domをインストールします。
npm i -S react-router-dom
package.jsonを確認すると現時点の最新は6.0.1になっています。
// package.jsonの一部
"react-dom": "17.0.2",
"react-router-dom": "^6.0.1",
ちなみに6系にアップデートされた際にいろいろと変更が入っているようです。
urlごとにコンポーネントを出しわけるルーティングを設定する
以下のように書くことによってルートにアクセスされたときはTopコンポーネントを表示して、/page1にアクセスされたときはPage1コンポーネントを表示することができます。
また、404 not foundの場合はpathパラメータをつけずに最後においておけば、見つからなかった時に表示されます。
// frontend/app_router/index.tsx
import { BrowserRouter, Route, Routes} from "react-router-dom";
import Top from "../pages/Top"
import Page1from "../pages/Page1"
import Page404 from "../page/Page404";
const AppRouter = () => {
return (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Top />} />
<Route exact path="/page1" element={<Page1 />} />
<Route component={<Page404 />} />
</Routes>
</BrowserRouter>
);
};
export default AppRouter;
Routesの中に
Routeのexactはpathに指定した文字列とアクセスしたpathが完全一致した場合のみコンポーネントを返す設定です。
exactを書いておくとtrueになり、省略するとfalseになります。
はまったポイント
以下のように書いて何も表示されませんでした。
// 古い例!
import { BrowserRouter, Route, Switch} from "react-router-dom";
import Top from "../pages/Top"
import Page1from "../pages/Page1"
const AppRouter = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={Top} />
<Route exact path="/page1" component={Page1} />
</Switch>
</BrowserRouter>
);
};
export default AppRouter;
コンパイル時やブラウザにこんなエラーが出てました。
WARNING in ./frontend/app_router/index.tsx 9:33-39
export 'Switch' (imported as 'Switch') was not found in 'react-router-dom' (possible exports: BrowserRouter, HashRouter, Link, MemoryRouter, NavLink, Navigate, Outlet, Route, Router, Routes, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, createRoutesFromChildren, createSearchParams, generatePath, matchPath, matchRoutes, renderMatches, resolvePath, useHref, useInRouterContext, useLinkClickHandler, useLocation, useMatch, useNavigate, useNavigationType, useOutlet, useParams, useResolvedPath, useRoutes, useSearchParams)
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `AppRouter`.
at AppRouter
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
react-dom.development.js?61bb:20085 The above error occurred in the <Location.Provider> component:
...
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
まず、SwitchはRoutesに名前が変わっているので、Routesを使いましょう。
次に引数のcomponentもelementに変わって、以前はcomponent={Top}というように書いていましたが、6系からelement={