リンクとナビゲーション
Next.jsでルート間をナビゲートする方法は4つあります:
<Link>
コンポーネントを使用するuseRouter
フックを使用する(Client Components)redirect
関数を使用する(Server Components)- ネイティブのHistory APIを使用する
このページでは、これらの各オプションの使用方法を説明し、ナビゲーションがどのように機能するかを詳しく見ていきます。
<Link>
コンポーネント
<Link>
はHTMLの<a>
タグを拡張した組み込みコンポーネントであり、プリフェッチとルート間のクライアントサイドナビゲーションを提供します。それは、Next.jsでルート間をナビゲートする際の主要かつ推奨される方法です。
next/link
からインポートし、このコンポーネントにhref
prop を渡して使用できます:
- TypeScript
- JavaScript
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
<Link>
に渡すことができるその他のオプションの props もあります。詳細はAPIリファレンスを参照してください。
useRouter()
フック
useRouter
フックを利用すると、Client Componentsからプログラム的にルートを変更できます。
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
useRouter
メソッドの完全なリストについては、APIリファレンスを参照してください。
おすすめ:
useRouter
を使用する特定の要件がない限り、ルート間をナビゲートするには<Link>
コンポーネントを使用してください。
redirect
関数
Server Componentsの場合、redirect
関数を使用してください。
- TypeScript
- JavaScript
import { redirect } from 'next/navigation'
async function fetchTeam(id: string) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }: { params: { id: string } }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}
import { redirect } from 'next/navigation'
async function fetchTeam(id) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}
Good to know:
redirect
はデフォルトで307(Temporary Redirect)ステータスコードを返します。Server Actionで使用すると、303(See Other)を返します。これはPOSTリクエストの結果として成功ページにリダイレクトする際によく使用されます。redirect
は内部でエラーをスローしますので、try/catch
ブロックの外部で呼び出す必要があります。redirect
はClient Componentsのレンダリングプロセス中には呼び出せますが、イベントハンドラー内では呼び出せません。その場合はuseRouter
フックを使用できます。redirect
は絶対URLも受け付け、外部リンクへのリダイレクトにも使用できます。- レンダリングプロセスの前にリダイレクトしたい場合、
next.config.js
またはMiddlewareを使用してください。
詳細については、redirect
APIリファレンスを参照してください。
ネイティブのHistory APIを使用する
Next.jsでは、ネイティブのwindow.history.pushState
とwindow.history.replaceState
メソッドを使用して、ページをリロードすることなくブラウザの履歴スタックを更新できます。
pushState
とreplaceState
の呼び出しはNext.js Routerに統合されており、usePathname
やuseSearchParams
と同期できます。
window.history.pushState
これを使用して、ブラウザの履歴スタックに新しいエントリを追加します。ユーザーは前の状態に戻ることができます。たとえば、製品のリストをソートするには次のようにします:
- TypeScript
- JavaScript
'use client'
import { useSearchParams } from 'next/navigation'
export default function SortProducts() {
const searchParams = useSearchParams()
function updateSorting(sortOrder: string) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}
return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
)
}
'use client'
import { useSearchParams } from 'next/navigation'
export default function SortProducts() {
const searchParams = useSearchParams()
function updateSorting(sortOrder) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}
return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
)
}
window.history.replaceState
これを使用して、ブラウザの履歴スタック上の現在のエントリを置き換えます。ユーザーは前の状態に戻ることはできません。たとえば、アプリケーションのロケールを切り替えるには次のようにします:
- TypeScript
- JavaScript
'use client'
import { usePathname } from 'next/navigation'
export function LocaleSwitcher() {
const pathname = usePathname()
function switchLocale(locale: string) {
// 例: '/en/about' または '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}
return (
<>
<button onClick={() => switchLocale('en')}>English</button>
<button onClick={() => switchLocale('fr')}>French</button>
</>
)
}
'use client'
import { usePathname } from 'next/navigation'
export function LocaleSwitcher() {
const pathname = usePathname()
function switchLocale(locale) {
// 例: '/en/about' または '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}
return (
<>
<button onClick={() => switchLocale('en')}>English</button>
<button onClick={() => switchLocale('fr')}>French</button>
</>
)
}