リンクとナビゲーション
Next.jsルーターを使用すると、シングルページアプリケーションと同様に、ページ間でクライアントサイドのルート遷移を実行できます。
このクライアントサイドのルート遷移を実行するために、`Link`と呼ばれるReactコンポーネントが提供されています。
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link href="/">Home</Link>
</li>
<li>
<Link href="/about">About Us</Link>
</li>
<li>
<Link href="/blog/hello-world">Blog Post</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')}>
Click here to read more
</button>
)
}
シャロールーティング
シャロールーティングを使用すると、`getServerSideProps`、`getStaticProps`、`getInitialProps`などのデータフェッチメソッドを再度実行せずに、URLを変更できます。
状態を失うことなく、`router` オブジェクト(`useRouter`または`withRouter`によって追加された)を介して、更新された `pathname` と `query` を受信します。
シャロールーティングを有効にするには、shallow
オプションを true
に設定します。次の例を考えてみましょう。
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// Current URL is '/'
function Page() {
const router = useRouter()
useEffect(() => {
// Always do navigations after the first render
router.push('/?counter=10', undefined, { shallow: true })
}, [])
useEffect(() => {
// The counter changed!
}, [router.query.counter])
}
export default Page
URL は /?counter=10
に更新されますが、ページ全体は置き換えられず、ルートの状態のみが変更されます。
以下に示すように、componentDidUpdate
を介して URL の変更を監視することもできます。
componentDidUpdate(prevProps) {
const { pathname, query } = this.props.router
// verify props have changed to avoid an infinite loop
if (query.counter !== prevProps.router.query.counter) {
// fetch data based on the new query
}
}
注意事項
シャロールーティングは、**現在のページ内での URL 変更に対してのみ**機能します。たとえば、pages/about.js
という別のページがあり、以下を実行するとします。
router.push('/?counter=10', '/about?counter=10', { shallow: true })
これは新しいページであるため、シャロールーティングを要求したとしても、現在のページがアンロードされ、新しいページがロードされ、データフェッチが待機されます。
シャロールーティングをミドルウェアと併用する場合、ミドルウェアを使用しない場合のように、新しいページが現在のページと一致することが保証されません。これは、ミドルウェアが動的に書き換えを行うことができ、シャローでスキップされるデータフェッチなしではクライアント側で検証できないためです。そのため、シャロールートの変更は常にシャローとして扱われる必要があります。
これは役に立ちましたか?