Linking and Navigating
Next.js router は、シングルページアプリケーションと同様に、ページ間で Client サイドの route 遷移を可能にします。
クライアントサイドの route 遷移を行うために、Link
と呼ばれる React component が提供されています。
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;
上記の例では複数のリンクを使用しています。それぞれが path (href
) を既知のページにマッピングします:
/
→pages/index.js
/about
→pages/about.js
/blog/hello-world
→pages/blog/[slug].js
<Link />
は viewport(初期または scroll を通じて)内にある場合、 Static Generationを使用するページについて、対応するデータを含めて default でプリフェッチされます。server-rendered routes の対応データは、<Link />
がクリックされたときのみ取得されます。
Linking to dynamic paths
あなたはまた、補間を使用して path を作成することもできます。これは dynamic route segments に便利です。たとえば、component として prop で渡された投稿リストを表示するためには:
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;
例の中で
encodeURIComponent
は、path を utf-8 と互換性を保つために使用されています。
あるいは、URL Object を使用する場合:
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;
今では、path を作成するために補間を使用する代わりに、href
で URL object を使用します。ここで:
pathname
はpages
ディレクトリ内のページ名です。この場合、/blog/[slug]
です。query
は dynamic セグメントを持つ object です。この場合、slug
。
Injecting the router
Examples
React component でrouter
objectにアクセスするには、useRouter
またはwithRouter
を使用できます。
一般的に、私たちはuseRouter
の使用をお勧めします。
Imperative Routing
next/link
はあなたのルーティングの要求事項の大部分を満たすべきですが、これなしでも Client サイドのナビゲーションを実行することができます。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>
);
}
Shallow Routing
Examples
Shallow ルーティングを使用すると、データフェッチ Method を再度実行せずに URL を変更できます。これには、getServerSideProps
、getStaticProps
、およびgetInitialProps
が含まれます。
pathname
とquery
のアップデートは、router
objectを経由して(useRouter
またはwithRouter
によって追加され)、状態を失うことなく受け取ることができます。
shallow ルーティングを有効にするには、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
に更新され、ページは置き換えられず、route の状態だけが変更されます。
以下に示すように、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
}
}
Caveats
Shallow ルーティングは、現在のページでの URL 変更にだけ対応しています。 例えば、もう一つのページpages/about.js
があり、それを実行するという状況を想定してみてください。
router.push("/?counter=10", "/about?counter=10", { shallow: true });
それが新しいページなので、現在のページをアンロードし、新しいページをロードし、データのフェッチングを待つことになります。それは我々が shallow ルーティングを行うように頼んだにも関わらずです。
shallow ルーティングが middleware と共に使用される場合、以前 middleware なしで行われていたように、新しいページが現在のページと一致することを保証しません。これは middleware が動的に rewrite でき、データ fetch なしでは client 側で検証できないためです。fetch は shallow でスキップされるため、shallow route の変更は常に shallow として扱われなければなりません。