🍣

【App Router】Next.js13でURLのクエリパラメーターを取得する方法

2023/08/11に公開

概要

Next.13のApp Routerでクエリパラメータを取得する方法で詰まったので、備忘録を残します。
従来はuseRouterを使って取得する方法が一般的だと思いますが、そのまま利用すると以下のようなエラーが発生します。

ReactServerComponentsError:

You have a Server Component that imports next/router. Use next/navigation instead.
Learn more: https://nextjs.org/docs/app/api-reference/functions/use-router

環境

  • Next.js 13.4
  • App Router

コード

クライアントコンポーネントで取得する場合

こちらの方法は簡単です。
検索すれば、すぐ出てくると思います。

page.tsx
"use client";

import { useSearchParams } from "next/navigation";

export default function Page() {
  const searchParams = useSearchParams();
  const pageNum = searchParams.get("page");

  return (
      <>
          <h1>Page</h1>
          <p>page: {pageNum}</p>
      </>
  );
}

参考: Functions: useSearchParams | Next.js

サーバーコンポーネントで取得する場合

useSearchParamsの注意点

Next.jsのドキュメントに"use client"を使ってクライアントコンポーネントにすると「そのファイルにインポートされた他のすべてのモジュール (子コンポーネントを含む) はクライアントバンドルの一部とみなされます」とあるように、できるだけサーバーコンポーネントにしたいケースがあると思います。

Once "use client" is defined in a file, all other modules imported into it, including child components, are considered part of the client bundle.

参考: Getting Started: React Essentials | Next.js

ですが、useSearchParamsはクライアントコンポーネントでのみ利用できるので、下記のように"use client"を指定せず、クライアントコンポーネントにしないとエラーが発生します。

page.tsx
import { useSearchParams } from "next/navigation";

export default function Page() {
  const searchParams = useSearchParams();
  const pageNum = searchParams.get("page");

  return (
      <>
          <h1>Page</h1>
          <p>page: {pageNum}</p>
      </>
  );
}

Error: useSearchParams only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/react-client-hook-in-server-component

ここで詰まりました。

解決法

解決方法は、至ってシンプルです。
propsにsearchParamsを指定して、そこから取得してあげることでサーバーコンポーネントでクエリパラメータを取得できます。

page.tsx
export default function Page({
  params,
  searchParams,
}: {
  params: { slug: string };
  searchParams: { [key: string]: string | string[] | undefined };
}) {
  const pageNum = searchParams.page;

  return (
    <>
      <h1>Page</h1>
      <p>page: {pageNum}</p>
    </>
  );
}

参考: File Conventions: page.js | Next.js

やはり、新しいものを触る時はドキュメントを読み込むことが大事ですね。

読んでいただき、ありがとうございました。

Discussion