路由

React Router / Next.js

推薦

Next.js

如果是新專案,它不只能切換頁面,還具備有利於搜尋的結構和發布網站的機制。本站也是用 Next.js 做的

比較效果

用每個函式庫做了同樣的東西,動手試試看。

React Router

比較程式碼

修改程式碼,右邊的預覽會跟著變化。

import { MemoryRouter, Routes, Route, Link, useParams, useLocation } from "react-router"

const items = [
  { slug: "apple", name: "蘋果", price: 45 },
  { slug: "orange", name: "橘子", price: 30 },
]

// 樣式(不是這個範例的重點)
const linkStyle = { color: "#18181b", textDecoration: "none", fontSize: 14 }

function Home() {
  return <h2 style={{ margin: 0, fontSize: 18 }}>首頁</h2>
}

function ItemList() {
  return (
    <div>
      <h2 style={{ margin: "0 0 8px", fontSize: 18 }}>商品列表</h2>
      <ul style={{ listStyle: "none", margin: 0, padding: 0 }}>
        {items.map((item) => (
          <li key={item.slug} style={{ padding: "8px 0", borderTop: "1px solid #f4f4f5" }}>
            <Link to={"/items/" + item.slug} style={linkStyle}>
              {item.name} →
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

function ItemDetail() {
  // 取出 URL 中的 :slug 部分(例如 apple)
  const { slug } = useParams()
  const item = items.find((i) => i.slug === slug)

  if (!item) {
    return <p>找不到這個商品</p>
  }

  return (
    <div>
      <h2 style={{ margin: 0, fontSize: 18 }}>{item.name}</h2>
      <p style={{ margin: "4px 0 12px", color: "#71717a" }}>NT${item.price}</p>
      <Link to="/items" style={linkStyle}>← 返回列表</Link>
    </div>
  )
}

// 顯示目前的 URL(範例裡看不到網址列)
function CurrentUrl() {
  const location = useLocation()
  return (
    <span style={{ marginLeft: "auto", padding: "2px 8px", borderRadius: 6, background: "#f4f4f5", color: "#71717a", fontSize: 12, fontFamily: "monospace" }}>
      {location.pathname}
    </span>
  )
}

export default function App() {
  return (
    // MemoryRouter:只在範例內部切換 URL(一般網站使用 BrowserRouter)
    <MemoryRouter>
      <div style={{ maxWidth: 360, margin: "0 auto", border: "1px solid #e4e4e7", borderRadius: 12, fontFamily: "system-ui, sans-serif", overflow: "hidden" }}>
        <nav style={{ display: "flex", alignItems: "center", gap: 16, padding: "10px 16px", borderBottom: "1px solid #f4f4f5" }}>
          <Link to="/" style={linkStyle}>首頁</Link>
          <Link to="/items" style={linkStyle}>商品列表</Link>
          <CurrentUrl />
        </nav>

        <div style={{ padding: 16 }}>
          {/* URL 與畫面的對照表(path = URL,element = 這時要顯示的畫面) */}
          <Routes>
            {/* 在「/」時顯示首頁 */}
            <Route path="/" element={<Home />} />
            {/* 在「/items」時顯示商品列表 */}
            <Route path="/items" element={<ItemList />} />
            {/* 在「/items/任意內容」時顯示商品詳情(:slug = 這裡放什麼都可以) */}
            <Route path="/items/:slug" element={<ItemDetail />} />
          </Routes>
        </div>
      </div>
    </MemoryRouter>
  )
}

用 Next.js 做出同樣的東西

app/page.tsx → /

export default function Page() {
  return <h2>首頁</h2>
}

app/items/page.tsx → /items

import Link from "next/link"
import { items } from "@/data/items"

export default function Page() {
  return (
    <div>
      <h2>商品列表</h2>
      <ul>
        {items.map((item) => (
          <li key={item.slug}>
            <Link href={"/items/" + item.slug}>{item.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

app/items/[slug]/page.tsx → /items/apple 等

import Link from "next/link"
import { notFound } from "next/navigation"
import { items } from "@/data/items"

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  // 取出 URL 中的 [slug] 部分(例如 apple)
  const { slug } = await params
  const item = items.find((i) => i.slug === slug)

  if (!item) {
    notFound()
  }

  return (
    <div>
      <h2>{item.name}</h2>
      <p>NT${item.price}</p>
      <Link href="/items">← 返回列表</Link>
    </div>
  )
}

比較

截至 2026 年 10 月

React Router

官方網站 ↗

特色

為 React 應用程式加上頁面切換的函式庫。用程式碼寫一張「這個 URL 就顯示這個畫面」的對照表。頁面內容在瀏覽器中組合出來

適用情境

替現有的 React 應用程式加上頁面。登入後使用的管理後台等,不需要被搜尋到的應用程式

Next.js

推薦官方網站 ↗

特色

用 React 打造網站的框架。資料夾和檔案的結構直接就是 URL(app/basics/page.tsx → /basics)。頁面在伺服器上產生後再送出

適用情境

新建一個想被搜尋到的網站:部落格、網路商店、服務介紹頁等