コンテンツにスキップ

useSearchParams

useSearchParams は、現在のURLのクエリ文字列を読み取るためのクライアントコンポーネントフックです。

useSearchParams は、URLSearchParamsインターフェースの読み取り専用バージョンを返します。

app/dashboard/search-bar.tsx
'use client'
 
import { useSearchParams } from 'next/navigation'
 
export default function SearchBar() {
  const searchParams = useSearchParams()
 
  const search = searchParams.get('search')
 
  // URL -> `/dashboard?search=my-project`
  // `search` -> 'my-project'
  return <>Search: {search}</>
}

Parameters

const searchParams = useSearchParams()

useSearchParams はパラメータを取りません。

戻り値

useSearchParams は、URLのクエリ文字列を読み取るためのユーティリティメソッドを含む、URLSearchParamsインターフェースの読み取り専用バージョンを返します。

  • URLSearchParams.get(): 検索パラメータに関連付けられた最初の値を返します。例:

    URLsearchParams.get("a")
    /dashboard?a=1'1'
    /dashboard?a=''
    /dashboard?b=3null
    /dashboard?a=1&a=2'1' - すべての値を取得するには getAll() を使用してください
  • URLSearchParams.has(): 指定されたパラメータが存在するかどうかを示すブール値を返します。例:

    URLsearchParams.has("a")
    /dashboard?a=1true
    /dashboard?b=3false
  • URLSearchParamsのその他の読み取り専用メソッド(getAll()keys()values()entries()forEach()toString())についてさらに学ぶことができます。

知っておくと良いこと:

  • useSearchParamsクライアントコンポーネントフックであり、サーバーコンポーネントでは部分的なレンダリング中の古い値の発生を防ぐためにサポートされていません
  • サーバーコンポーネントでsearchParamsに基づいたデータ取得を行いたい場合は、対応するPageのsearchParamsプロップを読み取るのがより良い選択肢となることがよくあります。その後、そのPage内の任意のコンポーネント(サーバーまたはクライアント)にpropsで渡すことができます。
  • アプリケーションに/pagesディレクトリが含まれている場合、useSearchParamsReadonlyURLSearchParams | nullを返します。null値は、getServerSidePropsを使用しないページのプリレンダリング中にsearch paramsを認識できないため、移行中の互換性のためのものです。

動作

静的レンダリング

ルートが静的にレンダリングされる場合、useSearchParamsを呼び出すと、最も近いSuspense境界までのクライアントコンポーネントツリーがクライアントサイドでレンダリングされます。

これにより、ルートの一部は静的にレンダリングされ、useSearchParamsを使用する動的な部分はクライアントサイドでレンダリングできるようになります。

useSearchParamsを使用するクライアントコンポーネントを<Suspense/>境界でラップすることをお勧めします。これにより、それより上位のクライアントコンポーネントは静的にレンダリングされ、初期HTMLの一部として送信できます。

例:

app/dashboard/search-bar.tsx
'use client'
 
import { useSearchParams } from 'next/navigation'
 
export default function SearchBar() {
  const searchParams = useSearchParams()
 
  const search = searchParams.get('search')
 
  // This will not be logged on the server when using static rendering
  console.log(search)
 
  return <>Search: {search}</>
}
app/dashboard/page.tsx
import { Suspense } from 'react'
import SearchBar from './search-bar'
 
// This component passed as a fallback to the Suspense boundary
// will be rendered in place of the search bar in the initial HTML.
// When the value is available during React hydration the fallback
// will be replaced with the `<SearchBar>` component.
function SearchBarFallback() {
  return <>placeholder</>
}
 
export default function Page() {
  return (
    <>
      <nav>
        <Suspense fallback={<SearchBarFallback />}>
          <SearchBar />
        </Suspense>
      </nav>
      <h1>Dashboard</h1>
    </>
  )
}

知っておくと良いこと:

  • 開発環境では、ルートはオンデマンドでレンダリングされるため、useSearchParamsはサスペンドせず、Suspenseなしでも動作するように見える場合があります。
  • 本番ビルド中、クライアントコンポーネントからuseSearchParamsを呼び出す静的ページは、Suspense境界でラップする必要があります。それ以外の場合、ビルドはMissing Suspense boundary with useSearchParamsエラーで失敗します。
  • ルートを動的にレンダリングしたい場合は、まずサーバーコンポーネントでconnection関数を使用して受信リクエストを待機することを推奨します。これにより、それ以降のすべてがプリレンダリングから除外されます。ルートを動的にする要因については、動的レンダリングガイドを参照してください。
  • すでにサーバーコンポーネントのページにいる場合は、searchParamsプロップを使用し、値をクライアントコンポーネントに渡すことを検討してください。
  • または、PageのsearchParamsプロップを直接クライアントコンポーネントに渡し、Reactのuse()でアンラップすることもできます。ただし、これはサスペンドするため、クライアントコンポーネントはSuspense境界でラップする必要があります。

動的レンダリング

ルートが動的にレンダリングされる場合、useSearchParamsはクライアントコンポーネントの初期サーバーレンダリング中にサーバーで利用可能になります。

例:

app/dashboard/search-bar.tsx
'use client'
 
import { useSearchParams } from 'next/navigation'
 
export default function SearchBar() {
  const searchParams = useSearchParams()
 
  const search = searchParams.get('search')
 
  // This will be logged on the server during the initial render
  // and on the client on subsequent navigations.
  console.log(search)
 
  return <>Search: {search}</>
}
app/dashboard/page.tsx
import { connection } from 'next/server'
import SearchBar from './search-bar'
 
export default async function Page() {
  await connection()
  return (
    <>
      <nav>
        <SearchBar />
      </nav>
      <h1>Dashboard</h1>
    </>
  )
}

知っておくと良いこと:

  • 以前は、ページにexport const dynamic = 'force-dynamic'を設定することで動的レンダリングを強制していました。代わりにconnection()を使用することを推奨します。これは、動的レンダリングを受信リクエストに意味的に関連付けるためです。

サーバーコンポーネント

ページ

ページ(サーバーコンポーネント)でsearch paramsにアクセスするには、searchParamsプロップを使用します。

レイアウト

ページとは異なり、レイアウト(サーバーコンポーネント)はsearchParamsプロップを受け取りません。これは、共有レイアウトがナビゲーション中に再レンダリングされないため、ナビゲーション間でsearchParamsが古くなる可能性があるからです。詳細は詳細な説明を参照してください。

代わりに、PageのsearchParamsプロップまたはクライアントコンポーネントのuseSearchParamsフックを使用します。これらはクライアント側で最新のsearchParamsで再レンダリングされます。

searchParamsの更新

新しいsearchParamsを設定するには、useRouterまたはLinkを使用できます。ナビゲーションが実行された後、現在のpage.jsは更新されたsearchParamsプロップを受け取ります。

app/example-client-component.tsx
'use client'
 
export default function ExampleClientComponent() {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()
 
  // Get a new searchParams string by merging the current
  // searchParams with a provided key/value pair
  const createQueryString = useCallback(
    (name: string, value: string) => {
      const params = new URLSearchParams(searchParams.toString())
      params.set(name, value)
 
      return params.toString()
    },
    [searchParams]
  )
 
  return (
    <>
      <p>Sort By</p>
 
      {/* using useRouter */}
      <button
        onClick={() => {
          // <pathname>?sort=asc
          router.push(pathname + '?' + createQueryString('sort', 'asc'))
        }}
      >
        ASC
      </button>
 
      {/* using <Link> */}
      <Link
        href={
          // <pathname>?sort=desc
          pathname + '?' + createQueryString('sort', 'desc')
        }
      >
        DESC
      </Link>
    </>
  )
}

バージョン履歴

バージョン変更履歴
v13.0.0useSearchParamsが導入されました。