前言 前面我們已經認識了基本的 React Router,接著我們要認識另一個觀念,也就是巢狀路由,而巢狀路由在實戰開發上是很常見的,因此這一篇我們就必須要來認識一下。
切換頁面 在開始介紹巢狀路由(Nested Routes)之前,我們要先認識一下 React Router 中的另一個東西也就是 Link,在前面的練習結尾處,我們用了一個很蠢的方式去切換路由,也就是直接透過瀏覽器的網址列輸入 /todolist 到 ToDoList 頁面,不得不說這種方式很蠢,你也不可能讓使用者用這種方式去切換路由對吧?那…實際上來講我們該怎麼做才對呢?
正確來講我們要使用 React Router 的 Link 來切換我們想要到達的頁面,所以這邊就先打開 main.jsx,先在這邊暫時加入 List 即可。
使用方式很簡單直接將 List 放在 Routes 外面就可以了,而這邊我稍微做了一下簡單版的導覽列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import React from 'react' import { HashRouter , Route , Routes , Link } from "react-router-dom" ;import ReactDOM from 'react-dom/client' import App from './App' import './index.css' import ToDoList from "./TodoList" ;ReactDOM .createRoot (document .getElementById ('root' )).render ( <React.StrictMode > <HashRouter > <nav className ="px-5 flex items-center h-[60px] bg-indigo-500 text-white" > <h1 className ="mr-auto text-2xl" > React TodoList</h1 > <ul className ="flex" > <li className ="mr-3" > <Link to ="/" className ="border p-3 hover:bg-indigo-600 duration-500" > Home</Link > </li > <li > <Link to ="/todolist" className ="border p-3 hover:bg-indigo-600 duration-500" > ToDoList</Link > </li > </ul > </nav > <Routes > <Route path ="/" element ={ <App /> } /> <Route path ="/todolist" element ={ <ToDoList /> } /> </Routes > </HashRouter > </React.StrictMode > )
請注意 Link 必須放在 HashRouter 裡面,否則噴這個錯誤訊息
Uncaught Error: useHref() may be used only in the context of a Router component.
那麼拉回到剛剛講到一半的部分,上面我們新增了兩個 Link,一個是首頁跟 ToDoList 頁面,接下來當你點上方任何一個連結都會發現下方畫面會跟著切換
我們可以看到 Link 的使用方式非常簡單,只需要戴上一個 to 參數並設定與 Route 中 Path 屬性相同名稱就可以成功到該頁面了。
有沒有覺得很像 Vue Router 的 router-link 呢?簡單讓你回憶一下 Vue Router 的導航切換方式。
1 <router-link to ="/todolist" > ToDoList</router-link >
巢狀路由 回到巢狀路由的部分,我們會發現有一個問題存在,我們所有的頁面都是在 / 底下,可是實際開發來講不可能通通都在 /,一定還會有 admin、dashboard 等等路由,然後掛在這些路由底下,舉例來講我們預期 Url 會變化成以下
1 2 https://www.example.com/#/admin https://www.example.com/#/admin/products
這時候你可能會想說…「那 Route 就這樣寫啊?有問題嗎?」
1 2 3 4 5 6 <Routes > <Route path ="/" element ={ <App /> } /> <Route path ="/todolist" element ={ <ToDoList /> } /> <Route path ="/admin" element ={ <ToDoList /> } /> <Route path ="/admin/products" element ={ <ToDoList /> } /> </Routes >
確實這樣子寫是可以達到前面所提的效果,但是 admin 的頁面與 user 的頁面必定會有一些不同,例如 admin 有自己的導覽列與 user 必定是不同的,總不可能 user 可以看到 admin 的功能操作吧?如果你真的這樣做的話,那麼就會導致所有頁面都吃到同一種導覽列,因此這邊就會需要使用到巢狀路由來達到 Layout 的概念。
那麼我們該如何撰寫巢狀路由呢?其實很簡單,你只需要將 Route 包在 Route 中就可以了,如下
1 2 3 4 5 6 7 8 <Routes > <Route path ="/" element ={ <App /> } > <Route path ="todolist" element ={ <ToDoList /> } /> </Route > <Route path ="/admin" element ={ <Admin /> } > <Route path ="products" element ={ <AdminProducts /> } /> </Route > </Routes >
接下來為了讓大家體感上更明顯一點,所以這邊請你將剛剛寫在 main.jsx 的導覽列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <nav className="px-5 flex items-center h-[60px] bg-indigo-500 text-white" > <h1 className ="mr-auto text-2xl" > React TodoList</h1 > <ul className ="flex" > <li className ="mr-3" > <Link to ="/" className ="border p-3 hover:bg-indigo-600 duration-500" > Home</Link > </li > <li > <Link to ="/todolist" className ="border p-3 hover:bg-indigo-600 duration-500" > ToDoList</Link > </li > <li > <Link to ="/admin" className ="border p-3 hover:bg-indigo-600 duration-500" > Admin</Link > </li > <li > <Link to ="/admin/products" className ="border p-3 hover:bg-indigo-600 duration-500" > AdminProducts</Link > </li > </ul > </nav>
全部移動到 App.jsx 中,並將後台頁面的 Link 改成 /admin 就好,另一個 /admin/products 則刪除,因此目前 App.jsx 呈現如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import { Link } from "react-router-dom" ;const App = ( ) => { return ( <> <nav className ="px-5 flex items-center h-[60px] bg-indigo-500 text-white" > <h1 className ="mr-auto text-2xl" > React TodoList</h1 > <ul className ="flex" > <li className ="mr-3" > <Link to ="/" className ="border p-3 hover:bg-indigo-600 duration-500" > Home</Link > </li > <li className ="mr-3" > <Link to ="/todolist" className ="border p-3 hover:bg-indigo-600 duration-500" > ToDoList</Link > </li > <li className ="mr-3" > <Link to ="/admin" className ="border p-3 hover:bg-indigo-600 duration-500" > Admin</Link > </li > </ul > </nav > <h1 > App</h1 > </> ) }export default App ;
這時候你應該會發現畫面滿空的,而且你點 ToDoList 也不會出現在畫面上,這邊原因是因為還要額外加上一個東西叫做 <Outlet /> 在 App.jsx,例如:放在 <h1>App</h1> 底下
1 2 3 4 5 6 import { Link , Outlet } from "react-router-dom" ; ... <h1>App </h1> <Outlet /> ...
放上 <Outlet /> 之後,你就可以看到畫面正常的切換了
當你點擊 Admin 時,你也會發現頁面就是很純粹的空白一片,不會有前台的 Navbar 出現,只會出現後台專用的 Navbar(我有微調 Admin.jsx),而這就是共用 Layout 的概念,也是巢狀路由概念
範例程式碼:React Router Example
後記 本文將會同步更新到我的部落格
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
Advertisement