【不具合のお知らせ】AndroidとiOSに関する一部記事で画像が読み込めない現象が発生しております。

【React Router v6系】React RouterでURLのクエリを取得する方法を解説

React Router バージョン6系でクエリを取得する方法を解説します。

/articles?page=1&search="abc"pagesearchの部分がURLのクエリです。

モグモグさん

これらのデータを取得してAPIを叩いたり画面の表示を切り替えたりということがよくありますね。

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

  • useLocationURLSearchParamsを使う方法
  • loaderを使う方法

モグモグさん

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

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

モグモグさん

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

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

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

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

ルーティング定義

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

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

ルーティング定義

/にアクセスすると<Top>ページが呼ばれるように設定しました。

<ErrorPage><Layout>は今回気にせずOKです。

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

export const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    errorElement: <ErrorPage />,
    children: [{ index: true, element: <Top /> }], // Topページはこの後作成します。
  },
]);

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

ルーティングを定義した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();

useLocationとURLSearchParamsでクエリを取得

それでは、Topコンポーネントでクエリを取得していきます。

useLocationを使ってURLのpathを取得し、URLSearchParamsでクエリを解析しています。

解析したオブジェクトは、get("クエリ名")が使えるようになります。

import { FC, useMemo } from "react";
import { useLocation } from "react-router-dom";

const useQuery = () => {
  const { search } = useLocation();

  return useMemo(() => new URLSearchParams(search), [search]);
};

export const Top: FC = () => {
  const query = useQuery();
  console.log(query)

  return (
    <div>
      <h1>Top Page</h1>
      <p>
        page: {query.get("page") || "empty"}, search: {query.get("search") || "empty"}
      </p>
    </div>
  );
};

動作確認

トップページ画面

/?page=1&search="test"にアクセスするとクエリが取得できていることがわかりますね。

クエリがない場合は、emptyと表示されます。

あとは取得したクエリを使ってAPIを叩いたり…のようなことを行うことが多いと思います。

loaderでパラメータを取得

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

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

ルートでloaderに関数を渡すとrequestからクエリを取得することができます。

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

const loader = async ({ request }: LoaderFunctionArgs) => {
  const query = new URL(request.url).searchParams;
  const page = query.get("page");
  const search = query.get("search");
  return { page, search };
};

export const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    errorElement: <ErrorPage />,
    children: [{ index: true, element: <Top />, loader: loader }],
  },
]);

Topページで取得

loaderの関数で返した値は、useLoaderData()の中に入っていますので戻り値を取得することができます。

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

export const Top: FC = () => {
  const { page, search } = useLoaderData() as { page: string; search: string };

  return (
    <div>
      <h1>Top Page</h1>
      <p>
        page: {page || "empty"}, search: {search || "empty"}
      </p>
    </div>
  );
};

動作確認

トップページ画面

/?page=1&search="test"にアクセスすると同様にクエリが取得できていることがわかりますね。

loaderのメリット

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

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

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

const loader = async ({ request }: LoaderFunctionArgs) => {
  const query = new URL(request.url).searchParams;
  const page = query.get("page");
  const search = query.get("search");
  // 例
  return await fetchSomeData(page, search);
};

まとめ

React Router バージョン6系でクエリを取得する方法を解説しました。

2パターン紹介したのでユースケースに合わせて使ってみてください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です