React Router バージョン6系を導入しページ遷移を行う方法を解説します。
Reactでページ遷移を行う場合は、React Routerを使用するのが一般的です。
- react 18.2.0
- react-router-dom 6.6.1
モグモグさん
本記事ではTypeScriptを使っています。
使っていない方は、tsx
をjsx
など適時置き換えていただけますと幸いです。
基本的なルーティング
導入から基本的なルーティング方法を解説していきます。
パッケージを追加
まずはパッケージを追加しましょう。
$ npm install react-router-dom
// yarn
$ yarn add react-router-dom
ページを作成する
例として、TopとPage1というページを作成します。
モグモグさん
すでにページを実装している方は不要です。
例のページは極端にシンプルにしています。
ディレクトリやファイル名は任意です。
Topページ作成
import { FC } from "react";
export const Top: FC = () => {
return (
<div>
<h1>Top Page</h1>
</div>
);
};
Page1を作成
import { FC } from "react";
export const Page1: FC = () => {
return (
<div>
<h1>Page 1</h1>
</div>
);
};
ルーティングを設定・管理するファイルを作成
アプリケーション上の全てのページ遷移の設定・管理を行うファイルを作成します。
import React from "react";
import { createBrowserRouter } from "react-router-dom";
import { Top } from "./screens/Top";
import { Page1 } from "./screens/Page1";
export const router = createBrowserRouter([
{ path: "/", element: <Top /> },
{ path: "page1", element: <Page1 /> },
]);
<BrowerRouter>
で囲うという書き方もできますが、createBrowserRouter
を使うことが公式では推奨されています。
DOM History APIを使っているのと、v6.4から追加されたData APIを使えるようにするためです。
ルートファイルで呼び出す
ルーティングを定義したAppRoutesをルートから呼び出します。
モグモグさん
ルートファイルはみなさんの環境に合わせてください!
本記事では、create-react-appを使っているのでsrc/index.tsx
がルートファイルになります。
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import reportWebVitals from "./reportWebVitals";
import { RouterProvider } from "react-router-dom";
import { router } from "./components/AppRoutes";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
動作確認
react-router-dom
の<Link>
を使うことでaタグを使ってでのページ遷移が可能になります。
Topページにリンクを追加
import { FC } from "react";
import { Link } from "react-router-dom";
export const Top: FC = () => {
return (
<div>
<h1>Top Page</h1>
<p>
<Link to="/page1">Page 1</Link>
</p>
</div>
);
};
Page1にリンクを追加
import { FC } from "react";
import { Link } from "react-router-dom";
export const Page1: FC = () => {
return (
<div>
<h1>Page 1</h1>
<p>
<Link to="/">Top</Link>
</p>
</div>
);
};
モグモグさん
これでビルドすると、ページ遷移ができていることが確認できます。
コードで遷移する
先ほどは、<Link>
を使ってHTMLで遷移しましたが、JSから遷移させることもできます。
TopページでリンクをonClickに変更
import { FC } from "react";
import { useNavigate } from "react-router-dom";
export const Top: FC = () => {
const navigate = useNavigate();
return (
<div>
<h1>Top Page</h1>
<p onClick={() => navigate("page1")}>Page 1</p>
</div>
);
};
Page1でリンクをonClickに変更
import { FC } from "react";
import { useNavigate } from "react-router-dom";
export const Page1: FC = () => {
const navigate = useNavigate();
return (
<div>
<h1>Page 1</h1>
<p onClick={() => navigate("/")}>Top</p>
</div>
);
};
モグモグさん
これでビルドすると、<Link>
と同様にページ遷移ができていることが確認できます。
エラーページを追加する
続いては存在しないURLにアクセスした場合や何かしらのエラーが発生した場合のエラーページを実装していきましょう。
エラー用ページ作成
この後実装しますが、errorElement
にこのページを渡すとuseRouteError
にはエラーの情報が入ってくるので404のエラーなのか、500のエラーなのか等が判別できて動的にデータを表示することも可能です。
ここではとりあえずエラーログだけ表示しています。
import { FC } from "react";
import { Link, useRouteError } from "react-router-dom";
export const ErrorPage: FC = () => {
const error = useRouteError();
console.log(error);
return (
<div>
<h1>Error!</h1>
<p>
<Link to="/">Go back to home.</Link>
</p>
</div>
);
};
errorElementに渡す
import React from "react";
import { createBrowserRouter } from "react-router-dom";
import { Top } from "./screens/Top";
import { Page1 } from "./screens/Page1";
import { ErrorPage } from "./screens/Error";
export const router = createBrowserRouter([
{ path: "/", element: <Top />, errorElement: <ErrorPage /> },
{ path: "page1", element: <Page1 /> },
]);
動作確認
適当なURLにアクセスすると、こんな感じでエラーページが表示されるようになりました!
今回は存在しないURLなので404エラーの情報がログに出力されていると思いますので確認ください。
共通レイアウトを導入する
次に共通レイアウトを導入していきましょう。
よくあるヘッダーとフッターを共通レイアウトとして中身だけページごとに入れ替えるようにします。
Layoutページを作成
モグモグさん
import { FC } from "react";
import { Link, Outlet } from "react-router-dom";
import { Box } from "@chakra-ui/react";
export const Layout: FC = () => {
return (
<>
<header>
<nav>
<ul>
<li>
<Link to="/">Top</Link>
</li>
<li>
<Link to="page1">Page 1</Link>
</li>
</ul>
</nav>
</header>
<main>
<Outlet />
</main>
<footer>
<div>
<p>Footer</p>
</div>
</footer>
</>
);
};
ルーティングを修正
element: <Layout />
: 共通のレイアウトを実装したページを指定。children
:<Outlet />
で呼ばれる子ルート群。index: true
: 親ルートのpath
で呼びたい場合に指定。
import React from "react";
import { createBrowserRouter } from "react-router-dom";
import { Top } from "./screens/Top";
import { Page1 } from "./screens/Page1";
import { ErrorPage } from "./screens/Error";
import { Layout } from "./screens/Layout";
export const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
errorElement: <ErrorPage />,
children: [
{ index: true, element: <Top /> },
{ path: "page1", element: <Page1 /> },
],
},
]);
動作確認
トップページにアクセスするとこんな感じで、ヘッダーとフッターのレイアウトの中でTopコンポーネントが呼ばれるようになります。
Page1に関しても同様です。
※本記事には含んでいませんが分かりやすいようにスタイルを少し修正しています。
childrenではなく入れ子(JSX)で定義する
機能上は変化はないですが、ルートを定義する場合にJSXの形で書くことが可能です。
createRoutesFromElements
を使います。
import React from "react";
import {
createBrowserRouter,
createRoutesFromElements,
Route,
} from "react-router-dom";
import { Top } from "./screens/Top";
import { Page1 } from "./screens/Page1";
import { ErrorPage } from "./screens/Error";
import { Layout } from "./screens/Layout";
export const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<Layout />} errorElement={<ErrorPage />}>
<Route index element={<Top />} />
<Route path="page1" element={<Page1 />} />
</Route>
)
);
モグモグさん
好みの問題なので、個人やチームの方針で決めましょう!
まとめ
React Router バージョン6系を導入しページ遷移を行う方法を解説しました。
- React Routerの導入方法
- ルーター定義方法
- リンクとコードからページ遷移する方法
- 共通レイアウトを定義する方法
これで基本的な内容は抑えられると思いますが、まだまだ重要で便利な使い方がありますので他の記事で解説していきます。
【React Router v6系】React RouterでDynamic Routingを実装する方法を解説
【React Router v6系】React Routerのloaderの基本を解説