リンクとナビゲーション
Next.jsでルート間を移動するには4つの方法があります。
<Link>
コンポーネントの使用useRouter
フックの使用 (クライアントコンポーネント)redirect
関数の使用 (サーバーコンポーネント)- ネイティブのHistory APIの使用
このページでは、これらの各オプションの使用方法について説明し、ナビゲーションの仕組みについて深く掘り下げます。
<Link>
コンポーネント
<Link>
は、HTMLの <a>
タグを拡張し、プリフェッチとルート間のクライアントサイドナビゲーションを提供する組み込みコンポーネントです。これはNext.jsでルート間を移動するための主要かつ推奨される方法です。
next/link
からインポートし、コンポーネントに href
プロパティを渡して使用できます。
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
<Link>
には、他にもオプションのプロパティを渡すことができます。詳細については、APIリファレンスを参照してください。
useRouter()
フック
useRouter
フックを使用すると、クライアントコンポーネントからプログラム的にルートを変更できます。
'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
関数
サーバーコンポーネントでは、代わりに redirect
関数を使用します。
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: Promise<{ id: string }>
}) {
const { id } = await params
if (!id) {
redirect('/login')
}
const team = await fetchTeam(id)
if (!team) {
redirect('/join')
}
// ...
}
ご存知でしたか:
redirect
はデフォルトで307 (Temporary Redirect) ステータスコードを返します。サーバーアクションで使用される場合、303 (See Other) を返します。これは、POSTリクエストの結果として成功ページにリダイレクトするためによく使用されます。redirect
は内部でエラーをスローするため、try/catch
ブロックの外で呼び出す必要があります。redirect
はレンダリングプロセス中にクライアントコンポーネントで呼び出すことができますが、イベントハンドラーでは呼び出すことができません。代わりにuseRouter
フックを使用できます。redirect
は絶対URLも受け入れ、外部リンクへのリダイレクトにも使用できます。- レンダリングプロセスより前にリダイレクトしたい場合は、
next.config.js
または ミドルウェアを使用してください。
詳細については、redirect
APIリファレンスを参照してください。
ネイティブの History API の使用
Next.jsでは、ネイティブの window.history.pushState
および window.history.replaceState
メソッドを使用して、ページをリロードせずにブラウザの履歴スタックを更新できます。
pushState
と replaceState
の呼び出しはNext.js Routerに統合されており、usePathname
および useSearchParams
と同期させることができます。
window.history.pushState
これを使用して、ブラウザの履歴スタックに新しいエントリを追加します。ユーザーは前の状態に戻ることができます。例えば、製品リストを並べ替える場合などです。
'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>
</>
)
}
window.history.replaceState
これを使用して、ブラウザの履歴スタック上の現在のエントリを置き換えます。ユーザーは前の状態に戻ることはできません。例えば、アプリケーションのロケールを切り替える場合などです。
'use client'
import { usePathname } from 'next/navigation'
export function LocaleSwitcher() {
const pathname = usePathname()
function switchLocale(locale: string) {
// e.g. '/en/about' or '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}
return (
<>
<button onClick={() => switchLocale('en')}>English</button>
<button onClick={() => switchLocale('fr')}>French</button>
</>
)
}
ルーティングとナビゲーションの仕組み
App Routerは、ルーティングとナビゲーションにハイブリッドアプローチを使用します。サーバー側では、アプリケーションコードはルートセグメントによって自動的にコード分割されます。そしてクライアント側では、Next.jsがルートセグメントをプリフェッチおよびキャッシュします。これにより、ユーザーが新しいルートに移動してもブラウザはページをリロードせず、変更されたルートセグメントのみが再レンダリングされ、ナビゲーション体験とパフォーマンスが向上します。
1. コード分割
コード分割により、アプリケーションコードをより小さなバンドルに分割し、ブラウザによってダウンロードおよび実行できるようになります。これにより、転送されるデータ量と各リクエストの実行時間が削減され、パフォーマンスが向上します。
サーバーコンポーネントは、アプリケーションコードをルートセグメントごとに自動的にコード分割することを可能にします。これにより、ナビゲーション時に現在のルートに必要なコードのみが読み込まれます。
2. プリフェッチ
プリフェッチとは、ユーザーがルートを訪れる前に、バックグラウンドでルートを事前に読み込む方法です。
Next.jsでルートがプリフェッチされる方法は2つあります。
<Link>
コンポーネント: ルートは、ユーザーのビューポートに表示されると自動的にプリフェッチされます。プリフェッチは、ページが最初にロードされたとき、またはスクロールによってビューに入ってきたときに発生します。router.prefetch()
:useRouter
フックを使用して、プログラム的にルートをプリフェッチできます。
<Link>
のデフォルトのプリフェッチ動作(つまり、prefetch
プロパティが未指定または null
に設定されている場合)は、loading.js
の使用方法によって異なります。共有レイアウトのみ、コンポーネントのレンダリングされた「ツリー」を下って最初の loading.js
ファイルまでがプリフェッチされ、30秒
間キャッシュされます。これにより、動的なルート全体をフェッチするコストが削減され、ユーザーに即時のローディング状態を表示して視覚的なフィードバックを向上させることができます。
prefetch
プロパティを false
に設定することで、プリフェッチを無効にできます。あるいは、prefetch
プロパティを true
に設定することで、ローディング境界を越えてページ全体のデータをプリフェッチできます。
詳細については、<Link>
APIリファレンスを参照してください。
ご存知でしたか:
- プリフェッチは開発環境では有効になっておらず、プロダクション環境でのみ有効です。
3. キャッシング
Next.jsには、Router Cache と呼ばれるインメモリのクライアントサイドキャッシュがあります。ユーザーがアプリ内を移動すると、プリフェッチされたルートセグメントや訪問済みのルートのReactサーバーコンポーネントペイロードがキャッシュに保存されます。
これにより、ナビゲーション時にキャッシュが可能な限り再利用され、サーバーへの新しいリクエストが行われる代わりに、リクエスト数と転送データ量を削減することでパフォーマンスが向上します。
Router Cache の仕組みと設定方法について詳しく学ぶことができます。
4. 部分レンダリング
部分レンダリングとは、ナビゲーション時に変更されるルートセグメントのみがクライアント側で再レンダリングされ、共有されるセグメントは保持されることを意味します。
例えば、/dashboard/settings
と /dashboard/analytics
という2つの兄弟ルート間を移動する場合、settings
ページはアンマウントされ、analytics
ページは新しい状態でマウントされ、共有の dashboard
レイアウトは保持されます。この動作は、同じ動的セグメント上の2つのルート間でも発生します。例えば、/blog/[slug]/page
で /blog/first
から /blog/second
へ移動する場合などです。

部分レンダリングがない場合、各ナビゲーションはクライアントでページ全体が再レンダリングされる原因となります。変更されたセグメントのみをレンダリングすることで、転送されるデータ量と実行時間が削減され、パフォーマンスが向上します。
5. ソフトナビゲーション
ブラウザはページ間を移動する際に「ハードナビゲーション」を実行します。Next.js App Routerはページ間の「ソフトナビゲーション」を可能にし、変更されたルートセグメントのみが再レンダリングされるようにします(部分レンダリング)。これにより、ナビゲーション中にクライアントのReactステートを保持できます。
6. 戻る・進むナビゲーション
デフォルトでは、Next.jsは「戻る」および「進む」ナビゲーションのスクロール位置を維持し、Router Cache 内のルートセグメントを再利用します。
7. pages/
と app/
間のルーティング
pages/
から app/
への段階的な移行時に、Next.jsルーターは両者間のハードナビゲーションを自動的に処理します。pages/
から app/
への遷移を検出するために、アプリルートの確率的チェックを利用するクライアントルーターフィルターがあり、これは時折誤検知を引き起こす可能性があります。デフォルトでは、誤検知の可能性は0.01%に設定されているため、そのような発生は非常にまれであるはずです。この可能性は、next.config.js
の experimental.clientRouterFilterAllowedRate
オプションを介してカスタマイズできます。誤検知率を下げると、クライアントバンドルで生成されるフィルターのサイズが増加することに注意することが重要です。
または、この処理を完全に無効にして pages/
と app/
間のルーティングを手動で管理したい場合は、next.config.js
で experimental.clientRouterFilter
を false に設定できます。この機能が無効になっている場合、app ルートと重複するページ内の動的ルートは、デフォルトでは適切にナビゲートされません。
次のステップ
参考になりましたか?