導覽與連結
有了頁面與路由之後,還需要讓使用者能在頁面之間移動。Next.js 提供 Link 元件做宣告式導覽,以及一組 Hook 做程式化導覽,兩者都會利用 App Router 的客戶端路由,切換頁面時不會整頁重新載入。
Link 元件
日常連結一律用 next/link 的 Link,不要用原生 <a>:
import Link from "next/link";
export default function Nav() {
return (
<nav>
<Link href="/">首頁</Link>
<Link href="/blog">部落格</Link>
<Link href={`/products/${id}`}>商品詳情</Link>
</nav>
);
}
Link 比 <a>多做了兩件事:
- 客戶端導覽 只更新畫面需要變動的部分,不會整頁重新載入、不會閃爍。
- 自動預先載入(Prefetch) 連結進入可視範圍時,Next.js 會在背景先抓好目標頁面的程式碼,點擊時幾乎是瞬間切換。
程式化導覽
按鈕點擊、表單送出成功後跳轉等情境,改用 useRouter(只能在 Client Component 使用,需要 "use client"):
"use client";
import { useRouter } from "next/navigation";
export default function LoginButton() {
const router = useRouter();
async function handleLogin() {
await login();
router.push("/dashboard"); // 導向新頁面,加入瀏覽紀錄
// router.replace("/dashboard"); // 導向新頁面,不加入瀏覽紀錄
// router.back(); // 回上一頁
}
return <button onClick={handleLogin}>登入</button>;
}
不要跟 Pages Router 搞混
App Router 的 useRouter 來自 next/navigation,API 跟舊版 Pages Router 的 next/router 不同(例如沒有 router.query),兩者不能混用。
取得目前路徑
想知道目前在哪一頁(例如做 Navbar 的作用中樣式),使用 usePathname;需要讀網址查詢字串則用 useSearchParams:
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
export default function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
const pathname = usePathname();
const isActive = pathname === href;
return (
<Link href={href} className={isActive ? "active" : ""}>
{children}
</Link>
);
}
下一步
會了路由與導覽之後,接著了解 Next.js 元件模型最核心的觀念:Server Components 與 Client Components 的差異,詳見 渲染與資料。