Menu

useSearchParams

useSearchParams は、現在の URL のクエリ文字列を読み取ることができるClient Component フックです。

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

app/dashboard/search-bar.tsx
TypeScript
'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}</>
}

パラメータ

const searchParams = useSearchParams()

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

戻り値

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

  • 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
  • getAll()keys()values()entries()forEach()toString()を含む、URLSearchParamsの他の読み取り専用メソッドの詳細を確認してください。

補足

  • useSearchParamsClient Componentフックであり、部分的なレンダリング中に古い値を防ぐため、Server Componentsではサポートされていません
  • Server Component でクエリパラメータに基づいてデータを取得する場合、対応する Page のsearchParamsプロパティを読み取る方がより良い選択肢となることがよくあります。その後、そのプロップを、そのページ内の任意のコンポーネント(Server または Client)に渡すことができます。
  • アプリケーションが /pages ディレクトリを含む場合、useSearchParamsReadonlyURLSearchParams | null を返します。null 値は、getServerSideProps を使用しないページの事前レンダリング中に検索パラメータを知ることができないため、移行中の互換性のためです。

動作

静的レンダリング

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

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

useSearchParams を使用する Client Component を <Suspense/> 境界で囲むことをお勧めします。これにより、上位の Client Components は静的にレンダリングされ、初期 HTML の一部として送信されます。

例えば:

app/dashboard/search-bar.tsx
TypeScript
'use client'
 
import { useSearchParams } from 'next/navigation'
 
export default function SearchBar() {
  const searchParams = useSearchParams()
 
  const search = searchParams.get('search')
 
  // 静的レンダリングを使用する場合、これはサーバーでログ出力されません
  console.log(search)
 
  return <>Search: {search}</>
}
app/dashboard/page.tsx
TypeScript
import { Suspense } from 'react'
import SearchBar from './search-bar'
 
// Suspense 境界にフォールバックとして渡されるこのコンポーネントは、
// 初期 HTML の検索バーの代わりにレンダリングされます。
// React ハイドレーション中に値が利用可能になると、フォールバックは
// `<SearchBar>` コンポーネントに置き換えられます。
function SearchBarFallback() {
  return <>placeholder</>
}
 
export default function Page() {
  return (
    <>
      <nav>
        <Suspense fallback={<SearchBarFallback />}>
          <SearchBar />
        </Suspense>
      </nav>
      <h1>Dashboard</h1>
    </>
  )
}

補足

  • 開発環境ではルートがオンデマンドでレンダリングされるため、useSearchParams は待機しないので、Suspense なしで動作しているように見えることがあります。
  • 本番ビルド中に、Client Component から useSearchParams を呼び出す静的ページは Suspense 境界でラップされていない場合、ビルドが失敗し、Missing Suspense boundary with useSearchParamsエラーが発生します。
  • ルートが動的にレンダリングされることを意図する場合、Server Component で最初にconnection関数を使用して、受信要求を待つことが好ましいです。これはその下のすべてを事前レンダリングから除外します。Dynamic Rendering ガイドでルートを動的にする要因を確認してください。
  • 既に Server Component ページにいる場合、searchParamsプロパティを使用して、その値を Client Components に渡すことを検討してください。
  • ページのsearchParamsプロパティを Client Component に直接渡して、React の use() でアンラップすることもできます。ただし、これは待機するため、Client Component は Suspense 境界でラップされるべきです。

動的レンダリング

ルートが動的にレンダリングされている場合、useSearchParams は Client Component の初期サーバーレンダリング中にサーバー上で利用可能になります。

例えば:

app/dashboard/search-bar.tsx
TypeScript
'use client'
 
import { useSearchParams } from 'next/navigation'
 
export default function SearchBar() {
  const searchParams = useSearchParams()
 
  const search = searchParams.get('search')
 
  // これは初期レンダリング中にサーバーでログ出力され、
  // その後のナビゲーション時にクライアントでログ出力されます。
  console.log(search)
 
  return <>Search: {search}</>
}
app/dashboard/page.tsx
TypeScript
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()の使用が推奨されます。これにより、動的レンダリングが受信要求に意味論的に結び付けられます。

Server Components

Pages

Pages(Server Components)でクエリパラメータにアクセスするには、searchParamsプロパティを使用します。

Layouts

Pages とは異なり、Layouts(Server Components)は searchParams プロパティを受け取りません。これは、共有レイアウトがナビゲーション中に再レンダリングされないため、ナビゲーション間で古い searchParams が発生する可能性があるためです。詳細な説明を確認してください。

代わりに、Page のsearchParamsプロパティ、または Client Component のuseSearchParamsフックを使用してください。これはクライアント上で最新の searchParams でレンダリングされます。

searchParams の更新

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

app/example-client-component.tsx
TypeScript
'use client'
 
export default function ExampleClientComponent() {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()
 
  // 現在の searchParams を提供された key/value ペアとマージして
  // 新しい searchParams 文字列を取得します
  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>
 
      {/* useRouter を使用 */}
      <button
        onClick={() => {
          // <pathname>?sort=asc
          router.push(pathname + '?' + createQueryString('sort', 'asc'))
        }}
      >
        ASC
      </button>
 
      {/* <Link> を使用 */}
      <Link
        href={
          // <pathname>?sort=desc
          pathname + '?' + createQueryString('sort', 'desc')
        }
      >
        DESC
      </Link>
    </>
  )
}

バージョン履歴

バージョン変更内容
v13.0.0useSearchParams が導入時期:導入されました。