前言
那麼由於我們主要都是以 React Hook 為主,因此 React Router 也有提供一些 Hook 給我們使用,所以這邊我們也要稍微了解一下有哪些 React Router Hook 是常見的。
常用的 Hook
這邊我也簡單列出常用的 React Router Hook
useLocation
useParams
useNavigate
useRoutes
後面這邊也會簡單寫一些範例來認識上面的常用 Hook。
useLocation
前面章節我們已經有使用到 useLocation 來做一些事情,那麼它主要是幹嘛呢?
底下有一個我們前面所使用的 <Link> 範例,這邊我們可以看到 <Link> 有一個 to 的屬性,那麼這個 to 屬性就是我們要去的路徑跟參數
1 2 3 4 5 6 7 8 9 10 11 12 13
| <Link to={{ pathname: '/products', search: 'q=ray', hash: '#products', }} state={{ products: { id: '1', name: 'QQ 產品' } }}> 產品詳細 </Link>
|
而當我們若要取得 <Link> 裡面參數時,我們就可以使用 useLocation 來取的相關資訊,底下是一個簡單範例
1 2 3 4 5 6 7 8 9 10 11
| import { useLocation } from "react-router";
const { hash, key, pathname, search, state } = useLocation(); useEffect(() => { console.log('hash:', hash); console.log('key:', key); console.log('pathname:', pathname); console.log('search:', search); console.log('state:', state); },[]);
|
就算你改用 <NavLink> 來取代 <Link> 也是可以的,因為 <NavLink> 也是使用 useLocation 來取得相關資訊。
useParams
useParams 絕對是實戰上最常用的 React Router Hook,那它主要使用在哪裡呢?舉例一個情境,我們實戰上常常會有一個頁面是要顯示產品詳細資訊,那麼這個頁面的路徑就會是 /products/:id,而 :id 就是我們要取得的參數,所以我們就可以使用 useParams 來取得 :id 的參數,因此 Route 可以這樣寫
1 2 3
| <Route path="/products" element={ <Products /> } > <Route path=":id" element={ <Product /> } /> </Route>
|
那麼為什麼會使用動態路由呢?因為我們不可能每個產品都要寫一個路徑,所以我們就可以使用動態路由來取得產品的 id,除此之外使用動態路由也有一個好處,當我們要分享產品給他人觀看時,我們就可以直接將產品的 id 丟到網址上,讓他人可以直接看到該產品的詳細資訊。
那麼如果要取得動態路由上的 :id 的話,就一定要使用 useParams
1 2 3 4 5 6 7
| import { useParams } from "react-router";
const { id } = useParams(); useEffect(() => { console.log('params id:', id); },[]);
|
透過 useParams 我們就可以輕鬆取得動態路由的 ID。
useNavigate
useNavigate 主要是用於重新導向,舉例來講當我們點了一個按鈕後,我們就可以使用 useNavigate 來重新導向到其他頁面,而底下範例就是重新導向到 /products/123 這個頁面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { useNavigate } from "react-router";
const Products = () => { const navigate = useNavigate();
return ( <> <h1>Products</h1> <button className="border-1 bg-indigo-500 p-3 text-white" onClick={ () => navigate('/products/123')} > 點我跳轉 </button> <Outlet /> </> ) }
export default Products;
|
當然也可以使用 useNavigate 來達到前一頁與後一頁
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 29 30 31 32
| import { useNavigate } from "react-router";
const Products = () => { const navigate = useNavigate();
return ( <> <h1>Products</h1> <button className="border-1 bg-indigo-500 p-3 text-white" onClick={ () => navigate('/products/123')} > 點我跳轉 </button> <button className="border-1 bg-indigo-500 p-3 text-white" onClick={ () => navigate(-1) } > 前一頁 </button> <button className="border-1 bg-indigo-500 p-3 text-white" onClick={ () => navigate(1) } > 後一頁 </button> <Outlet /> </> ) }
export default Products;
|
基本上就算你是傳入字串也是可以正常運作的 () => navigate('1')、() => navigate('-1')。
useRoutes
還記得我們前面 React Router 是如何建立的嗎?忘了也沒有關係,底下這邊也會附上範例
1 2 3 4 5 6 7 8 9 10
| <HashRouter> <Routes> <Route path="/" element={ <App /> } > <Route path="todolist" element={ <ToDoList /> } /> </Route> <Route path="/admin" element={ <Admin /> } > <Route path="products" element={ <AdminProducts /> } /> </Route> </Routes> </HashRouter>
|
相信有些人對於這種寫法不是很滿意,因為稍微有一點巢狀結構,而實戰上本身就會有很多巢狀結構,當結構過度巢狀時就會發生維護上的困擾,因此如果你不喜歡這種寫法的話,你可以使用 useRoutes 重新包裝。
那該如何使用 useRoutes 呢?首先這邊先建立一個專門管理 Router 的檔案,整體寫法會與你在使用 Vue Router 有 87% 神似,所以我這邊就將上方的範例改用 useRoutes 來寫
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 29 30 31 32 33 34
| import { useRoutes } from 'react-router-dom';
import App from '../App'; import ToDoList from "../TodoList";
import Admin from "../admin/Index"; import AdminProducts from "../admin/Products";
const routes = [ { path: '/', element: <App />, children: [ { path: '/todoList', element: <ToDoList />, }, ], }, { path: '/admin', element: <Admin />, children: [ { path: 'products', element: <AdminProducts />, }, ], } ];
export default () => useRoutes(routes);
|
接下來回到 main.jsx 將內容改成以下即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from 'react' import { HashRouter, Route, Routes, Link } from "react-router-dom"; import ReactDOM from 'react-dom/client' import './index.css'
import Router from './router';
ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <HashRouter> <Router /> </HashRouter> </React.StrictMode> )
|
這樣子畫面就會如同前面相同,但整體程式碼卻也更簡潔,而且也非常神似 Vue Router 的寫法。
那麼這一篇差不多介紹到這邊,而這一篇就不提供範例了,讓你自己試著去實作看看哩。
後記
本文將會同步更新到我的部落格
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
Advertisement