リンクとナビゲーション
Next.jsのルーターは、シングルページアプリケーションと同様に、ページ間のクライアントサイドルート遷移を可能にします。
クライアントサイドルート遷移を行うために、Link
という名前のReactコンポーネントが提供されています。
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link href="/">ホーム</Link>
</li>
<li>
<Link href="/about">会社概要</Link>
</li>
<li>
<Link href="/blog/hello-world">ブログ投稿</Link>
</li>
</ul>
)
}
export default Home
上記の例では、複数のリンクを使用しています。それぞれのリンクは、既知のページにパス(href
)をマッピングしています:
/
→pages/index.js
/about
→pages/about.js
/blog/hello-world
→pages/blog/[slug].js
ビューポート内の任意の<Link />
は、静的生成を使用するページでは、デフォルトで(対応するデータとともに)プリフェッチされます。サーバーサイドレンダリングされるルートの対応するデータは、<Link />
がクリックされた場合にのみフェッチされます。
動的パスへのリンク
補間を使用してパスを作成することもできます。これは、動的ルートセグメントに便利です。例えば、コンポーネントにプロップとして渡された投稿のリストを表示するには:
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${encodeURIComponent(post.slug)}`}>
{post.title}
</Link>
</li>
))}
</ul>
)
}
export default Posts
パスをUTF-8互換にするために、この例では
encodeURIComponent
を使用しています。
または、URLオブジェクトを使用する方法:
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link
href={{
pathname: '/blog/[slug]',
query: { slug: post.slug },
}}
>
{post.title}
</Link>
</li>
))}
</ul>
)
}
export default Posts
今回は、パスを作成するために補間を使用する代わりに、href
でURLオブジェクトを使用しています:
pathname
はpages
ディレクトリ内のページ名です。この場合は/blog/[slug]
。query
は動的セグメントを持つオブジェクトです。この場合はslug
。
ルーターの注入
例
Reactコンポーネントでrouter
オブジェクトにアクセスするには、useRouter
またはwithRouter
を使用します。
一般的に、useRouter
の使用をお勧めします。
命令的ルーティング
next/link
がほとんどのルーティングニーズをカバーできますが、クライアントサイドのナビゲーションを行わずに、next/router
のドキュメントを参照してください。
以下の例は、useRouter
を使用した基本的なページナビゲーションを示しています:
import { useRouter } from 'next/router'
export default function ReadMore() {
const router = useRouter()
return (
<button onClick={() => router.push('/about')}>
詳細を読むにはここをクリック
</button>
)
}
シャローRouting
シャローRoutingにより、データフェッチメソッドを再実行せずにURLを変更できます。これにはgetServerSideProps
、getStaticProps
、getInitialProps
が含まれます。
useRouter
またはwithRouter
によって追加されたrouter
オブジェクトを介して、状態を失うことなく、更新されたpathname
とquery
を受け取ります。
シャローRoutingを有効にするには、shallow
オプションをtrue
に設定します。以下の例を考えてみましょう:
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// 現在のURLは'/'
function Page() {
const router = useRouter()
useEffect(() => {
// 最初のレンダリング後に常にナビゲーションを行う
router.push('/?counter=10', undefined, { shallow: true })
}, [])
useEffect(() => {
// カウンターが変更された!
}, [router.query.counter])
}
export default Page
URLは/?counter=10
に更新され、ページは置き換えられず、ルートの状態のみが変更されます。
また、以下のようにcomponentDidUpdate
を介してURLの変更を監視することもできます:
componentDidUpdate(prevProps) {
const { pathname, query } = this.props.router
// 無限ループを避けるために、プロップが変更されたことを確認
if (query.counter !== prevProps.router.query.counter) {
// 新しいクエリに基づいてデータをフェッチ
}
}
注意点
シャローRoutingのみが、現在のページのURL変更で機能します。例えば、pages/about.js
という別のページがあり、以下を実行するとします:
router.push('/?counter=10', '/about?counter=10', { shallow: true })
これは新しいページであるため、現在のページをアンロードし、新しいページをロードし、シャローRoutingを要求したにもかかわらず、データフェッチを待機します。
ミドルウェアでシャローRoutingを使用する場合、以前のミドルウェアなしの動作とは異なり、新しいページが現在のページと一致することを保証できません。これは、ミドルウェアが動的に書き換えることができ、シャローでスキップされるデータフェッチなしではクライアントサイドで検証できないためです。したがって、シャローなルート変更は常にシャローとして扱う必要があります。