サイト名変更・お引越しのお知らせ

【React Router v6系】React RouterでDynamic Routingを実装する方法を解説

React Router バージョン6系でDynamic Routingを実装する方法を解説します。

/articles/1/articles/2にアクセスすると1や2のpath部分を動的にできるものです。

※ダイナミックセグメント(dynamic segment)と公式ページでは紹介されています。

今回2パターンを解説します。

  • useParamsを使う方法
  • loaderを使う方法

モグモグさん

loaderはv6.4から登場した新しい機能で、ユーザー体験の向上にもつながるのでこちらを使うことをオススメします。

バージョン
  • react 18.2.0
  • react-router-dom 6.6.1

モグモグさん

本記事ではTypeScriptを使っています。

使っていない方は、tsxjsx、型定義を削除するなど適時置き換えていただけますと幸いです。

ルーティングの基本についてはこちらで解説しています。

【React Router v6系】React Routerを導入し基本的なページ遷移を行う方法を解説

Dynamic Routing定義

まずはルーティングを作成しDynamic Routingを定義していきます。

例なので出来るだけシンプルな形で定義していきます。

ルーティング定義

path: ":slug"の箇所が重要です。

これでDynamic Routingになります

Articleページで、slugというパラメータが取得できます。

モグモグさん

例えば、slugをidにすればidというパラメータが取得できます。

import React from "react";
import { createBrowserRouter } from "react-router-dom";
import { ErrorPage } from "./screens/Error";
import { Layout } from "./screens/Layout";
import { Article } from "./screens/Article";

export const router = createBrowserRouter([
  {
    path: "/articles",
    element: <Layout />,
    errorElement: <ErrorPage />,
    children: [{ path: ":slug", element: <Article /> }],
  },
]);

ルートファイルでルーティングを定義したファイルを呼び出す

ルーティングを定義したAppRoutesをルートから呼び出します

モグモグさん

ルートファイルはみなさんの環境に合わせてください!

本記事では、create-react-appを使っているのでsrc/index.tsxがルートファイルになります。

ルーティングを定義したファイルを作成せず、ルートファイルに直接書いてももちろんOKです。

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();

useParamsでパラメータを取得

それでは、Articleコンポーネントでslugを取得していきます。

import { FC, useEffect } from "react";
import { useParams } from "react-router-dom";

export const Article: FC = () => {
  const { slug } = useParams();

  useEffect(() => {
    // Do something with slug
  }, [slug]);

  return (
    <div>
      <h1>slug</h1>
    </div>
  );
};

例えば、articles/abcとすると<h1>にはabcが表示されます。

あとは取得したパラメータを使ってAPIを叩いたり…のようなことを行うことが多いと思います。

loaderでパラメータを取得

続いて、loaderを使うパターンで取得してみましょう。

ルーティングファイルにloaderを追加

ルートでloaderに関数を渡すとパラメータを取得することができます。

import React from "react";
import { createBrowserRouter, LoaderFunctionArgs } from "react-router-dom";
import { ErrorPage } from "./screens/Error";
import { Layout } from "./screens/Layout";
import { Article } from "./screens/Article";

const articleLoader = async ({ params }: LoaderFunctionArgs) => {
  return params.slug;
};

export const router = createBrowserRouter([
  {
    path: "/articles",
    element: <Layout />,
    errorElement: <ErrorPage />,
    children: [{ path: ":slug", element: <Article />, loader: articleLoader }],
  },
]);

Articleページで取得

loaderの関数で返した値は、useLoaderData()の中に入っていますので動的なパラメータを取得することができます。

import { FC } from "react";
import { useLoaderData } from "react-router-dom";

export const Article: FC = () => {
  const slug = useLoaderData();
  console.log(slug);

  return (
    <div>
      <h1>{slug}</h1>
    </div>
  );
};

loaderのメリット

例ではただslugを返していましたが、実際にはloaderの関数の中でAPIを叩くなどの処理を行いそのレスポンスをページに返すという実装をすることが多いです。

loaderは画面の表示前に動くので事前にデータを取得した状態でページを表示することができます。

これがloaderのメリットです。

import React from "react";
import { createBrowserRouter, LoaderFunctionArgs } from "react-router-dom";
import { ErrorPage } from "./screens/Error";
import { Layout } from "./screens/Layout";
import { Article } from "./screens/Article";

const articleLoader = async ({ params }: LoaderFunctionArgs) => {
  // 例
  return await fetchSomething(params.slug);
};

export const router = createBrowserRouter([
  {
    path: "/articles",
    element: <Layout />,
    errorElement: <ErrorPage />,
    children: [{ path: ":slug", element: <Article />, loader: articleLoader }],
  },
]);

まとめ

React Router バージョン6系でDynamic Routingを実装する方法を解説しました。

loaderを使ってより良いユーザー体験を目指してみてください。