React Router v6:
SPA 路由完整指南
BrowserRouter、動態路由 :id、Outlet 巢狀、Loader/Action — 非 Next.js 的 React 應用必學
Section 1:為什麼需要路由
在沒有路由之前,React SPA(Single Page Application)整個網站只有一個 URL(/)。用戶按上一頁、加書籤、分享連結,全部都回到首頁,完全無法指向特定內容。React Router 讓你的 SPA 有真正意義上的 URL,讓每個畫面都有自己的地址。
SPA 路由的核心原理
沒有路由的問題
- • 所有頁面共用
/ - • 上一頁按鈕無效
- • 書籤永遠回到首頁
- • 分享連結無法指向特定頁面
- • SEO 幾乎不可能
有路由之後
- • 每個頁面有獨立 URL
- • 瀏覽器歷史記錄正常運作
- • 書籤可以指向任意頁面
- • 分享連結可以精確導向
- • SSR/預渲染配合 SEO
React Router vs Next.js App Router
你可能會問:「我已經在用 Next.js 了,為什麼要學 React Router?」答案是:不是所有 React 專案都是 Next.js。
| 比較 | Next.js App Router | React Router v6 |
|---|---|---|
| 路由方式 | 檔案系統(EP.18 已學) | 程式碼定義 |
| 適用環境 | Next.js 框架 | CRA / Vite / 任何 React |
| SSR 支援 | 原生支援 | 需另外配置 |
| 路由定義 | app/page.tsx 自動對應 | <Route> 組件聲明 |
| 資料載入 | Server Components / fetch | loader / action(v6.4+) |
| 部署 | Vercel 最佳化 | 任何靜態主機 |
學習這篇的意義:React Router 是全球最多 React 專案使用的路由方案,閱讀大量開源專案、維護舊版 React app、或到不使用 Next.js 的公司工作,都會需要它。它的概念也有助於更深入理解 Next.js 路由的設計思路。
Section 2:基本設定
React Router v6 的安裝與初始設定非常簡單。核心概念只有三個:BrowserRouter(提供路由環境)、Routes + Route(定義路由規則)、Link(宣告式導航連結)。
安裝
入口點設定(main.tsx)
BrowserRouter 必須包在最外層,提供路由的 context 給所有子元件使用。它內部使用瀏覽器的 History API 來同步 URL 與 UI。
App.tsx — 定義所有路由
Link vs NavLink 的差別
Link 是基本的路由連結,相當於不會觸發整頁刷新的 <a>。NavLink 在 URL 匹配時,className 函式會收到 { isActive },讓你可以動態設定「選中」樣式,非常適合導覽列。
Section 3:動態路由與 useParams
動態路由是 SPA 最常用的功能之一,讓同一個元件可以根據 URL 參數渲染不同內容。路由定義中的 :id 語法表示這段路徑是動態參數,在元件中用 useParams 取得。
useParams 基本用法
多層動態路由
一個路由中可以有多個動態參數。例如「某位使用者的特定文章」,URL 結構為 /users/:userId/posts/:postId。
Optional 參數與萬用路由
Section 4:巢狀路由與 Outlet
巢狀路由(Nested Routes)是 React Router v6 最強大的功能之一。它讓你定義共享 Layout 的路由群組,子路由的內容渲染在父路由 Layout 的 <Outlet /> 位置。
巢狀路由的實際場景
最典型的例子是後台 Dashboard:左側有導覽列(Sidebar),右側渲染不同的子頁面,但 Sidebar 永遠保持在畫面上。
DashboardLayout 元件
index route 的用途
<Route index /> 相當於父路由的「預設子頁面」。當 URL 精確匹配父路由時(例如 /dashboard),渲染 index 的元件。沒有 index route 的話,精確匹配父路由時 Outlet 會是空的。
Section 5:程式化導航 — useNavigate
Link 是使用者點擊觸發的宣告式導航。但很多情境需要在程式碼中觸發導航,例如:登入成功後跳轉到 dashboard、表單送出後跳轉到列表頁、沒有登入時重定向到登入頁。這時要用 useNavigate。
基本用法
navigate 的各種用法
Protected Route — 路由守衛
結合 useNavigate 和 useEffect 可以實作「需要登入才能訪問」的路由保護:
Section 6:Loader 和 Action(v6.4+ 的資料路由)
React Router v6.4 引入了「資料路由」(Data Routers)的概念,這是一個重大升級。它讓路由本身可以負責資料載入(Loader)和資料提交(Action),概念上與 Next.js 的 Server Components 和 Server Actions 非常相近,但在純客戶端環境中運行。
從 BrowserRouter 遷移到 createBrowserRouter
使用 Loader/Action 需要改用 createBrowserRouter 的物件定義方式,而不是 JSX 的 <Route> 元件。
Loader — 路由級別的資料載入
Action — 處理表單提交
Loader vs useEffect 的差異
使用 useEffect 的問題
- • 元件掛載後才開始 fetch
- • 需要管理 loading / error state
- • 頁面出現空白的閃爍
- • 路由切換時有 loading 空窗
使用 Loader 的優點
- • 路由切換時平行載入資料
- • 元件渲染時資料已就緒
- • 不需要 loading state
- • 錯誤自動顯示 errorElement
Section 7:useSearchParams — 查詢字串管理
查詢字串(Query String)就是 URL 中 ? 後面的部分,例如 /products?category=electronics&page=2。它非常適合用來存放篩選條件、排序方式、分頁等「可以分享、可以書籤」的 UI 狀態。React Router 提供 useSearchParams 讓你輕鬆讀寫查詢字串。
基本用法
搜尋功能實作
可分享
URL 包含所有篩選狀態
可書籤
下次打開還原篩選條件
上一頁有效
瀏覽器歷史正確記錄