公式ドキュメントの和訳を基本にしています。
https://nextjs.org/docs/#routing
Next.jsは各route(レスポンスを返すべきURL)に他のrouteの一覧を配信しているわけではないので、
クライアントサイドのページは他のページについて何も知りません。
スケーラビリティのため、後続のページは全てlazy-loadされます。
以下、Next.jsにおけるページ遷移の方法です。
next/linkを使う
next/linkはNext.jsについてくるルーティング用のコンポーネントです。<a />をこれでラップすると、クライアントサイドでのページ遷移を起こせます。
ほとんどのサイト内リンクはこれを使うことになるでしょう。
hrefとasを渡す
以下の2つのページについて考えます。
// pages/index.js
import Link from 'next/link'
function Home() {
return (
<div>
詳しくは
<Link href="/about">
<a>こちら</a>
</Link>
をクリックしてください
</div>
)
}
export default Home
// pages/about.js
function About() {
return <p>ほら詳しいでしょう</p>
}
export default About
next/linkは以下のpropsを受け付けます。
-
href: パス+クエリ文字列。唯一の必須props。 -
as: 遷移後ブラウザのURLバーに表示されるパス。 -
passHref: 子コンポーネントにhrefpropsを渡すか。デフォルトはfalse。子が<a>の場合は自動でパスするので、設定不要です。子がオリジナルのコンポーネントの場合(styled-componentsでMyStyledLinkを作っているなど)、trueにすることで href属性が出現し、SEOフレンドリーにできます。 -
prefetch: バックグラウンドでリンク先をプリフェッチするか。デフォルトはtrue。ただしfalseにしてもhover時にはプリフェッチされます。プリフェッチ機能はプロダクションビルドでのみ機能します。 -
replace: 遷移時、historyスタックに遷移先URLを追加する代わりに、現在のURLを置換します。デフォルトはfalse。 -
shallow: データフェッチ(getInitial/getStatic/getServerside props)もページリロードもせずにURLを変えるモード。デフォルトはfalse。該当の/pagesファイルが変わると必ず別ページになるので、クエリを変えるときにしか効果はありません。例えばラーメンの種類を選ぶページで ?ramen_kind=hakata に遷移するなどでしょうか。使ったことがない
function Page() {
const router = useRouter()
useEffect(() => {
// 新ラーメンの表示
}, [router.query.ramen_kind])
return (
<Link href="/ramen?ramen_kind=hakata">
<a>博多ラーメンを選ぶ</a>
</Link>
)
}
-
locale: 多言語対応時、選択中のlocaleを自動的に先頭につける。デフォルトはtrue。
この、next/linkでのクライアントサイドルーティングは、ブラウザの通常のルーティングと同じように動きます。
- コンポーネントが取得されます
- コンポーネントに
getInitialPropsがあれば、データが取得されます。エラーが発生すれば、_error.jsがレンダリングされます。 - 1と2が終わったら、
pushStateが実行され、コンポーネントがレンダリングされます。
URLオブジェクトを渡す
next/linkはURLオブジェクトを渡して使うこともでき、その場合オブジェクトは自動的にURL文字列に変換されます。
import Link from 'next/link'
function Home() {
return (
<div>
アザラシについては
<Link href={{ pathname: '/about', query: { animal: 'seal' } }}>
<a>こちら</a>
</Link>
をクリック
</div>
)
}
export default Home
この場合、URL文字列/about?animal=sealが生成されます。Node.jsのURLモジュールで定義されているプロパティは何でも利用できます。
next/routerを使う
クライアントサイドの遷移はnext/routerでも実現できます。
クリック以外のトリガー遷移するときや、遷移のロジックがフクザツなときに使えそうです。
router.push(url, as, options)
import { useRouter } from 'next/router'
function ActiveLink({ children, href }) {
const router = useRouter()
const handleClick = (e) => {
e.preventDefault()
router.push(href)
}
return (
<a href={href} onClick={handleClick}>
{children}
</a>
)
}
export default ActiveLink
optionsはnext/linkのpropsと似ています。
-
href: パス+クエリ文字列。 -
as: 遷移後ブラウザのURLバーに表示されるパス。 -
options: next/linkと同じ、shallowlocale