有太多新手在基礎還不熟的情況下,只因為路由設定的原因,改學用 Next 框架,但相信我 React-router-dom 真的不難,而且在選擇用不用 Next 的考量不能只是考量 router,更重要的是在架構和渲染機制這篇文章中所提及的概念,那麼這次的分享就是教大家如何整理到能簡單的使用 React-router-dom。
要學好一樣東西,熟讀官方文件是每個工程師必備的基本義務(官方連結)。當然,我會提供我濃縮完的版本,所以基礎的話可以自行參閱。
步驟 1 — 安裝 react-router-dom
npm i react-router-dom
// or
yarn add react-router-dom
那我這邊目前的版本是 ver. 6.x 的,我不建議拉 ver. 5.x,除非你是維護或是重構舊專案。
步驟 2 — 在 App.tsx 裡面引入 BrowserRouter 將整個 app 的 dom 包住(這裡的例子我是以 vite react 的方式建構專案的),這裡是從我 github 教學檔案拆出來的範例,詳細可以參考連結。
import { FC } from "react"
import { BrowserRouter, Link, Route, Routes } from "react-router-dom"
import About from "./pages/About"
import Contact from "./pages/Contact"
import Home from "./pages/Home"
import NotFonud from "./pages/NotFonud"
import Shirts from "./pages/Shirts"
import ShirtWid from "./pages/Shirts/ShirtWid"
import Shop from "./pages/Shop"
// BrowserRouter 就像 redux 的 provider 一樣,必須在最上層來處理
// Routes 裡面包的事處理所有路由導向的頁面
// Route 代表的是該路徑下需要渲染的 components
// 為了方便示範我先生成幾個頁面在 pages 的資料夾內
const App: FC = () => {
// navbar可自行腦補方便跳轉頁面的component
return (
<BrowserRouter>
<Navbar/>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
<Route path="shop" element={<Shop />} >
<Route path="shirts">
{/* nesting 的做法 */}
<Route index element={<Shirts/>} />
<Route path=":id" element={<ShirtWid/>} />
</Route>
</Route>
<Route path="contact" element={<Contact />} />
{/* 對未設定的路由可以採以下方式 */}
<Route path="*" element={<NotFonud />} />
</Routes>
</BrowserRouter>
)
}
export default App
上面是基本的應用範例,接下來的步驟是將其濃縮,讓他更為方便管理。
步驟 3 — 在根目錄下新增RouteConf.tsx的檔案,然後將原本在 Routes 裡面的邏輯做更改如下:
import React from 'react'
import { useRoutes } from 'react-router-dom'
import Layout from './components/Layout'
import About from './pages/About'
import Contact from './pages/Contact'
import Home from './pages/Home'
import Pants from './pages/Pants'
import PantWid from './pages/Pants/PantWid'
import Shirts from './pages/Shirts'
import ShirtWid from './pages/Shirts/ShirtWid'
import Shop from './pages/Shop'
// 這就是比較推薦的做法,將所有的routes拆出來做統一的管理
// 包含了每一層的從屬關係,都可以透過下列的表很清處的看到
// 這裡我們可以嘗試使用react-router-dom 的 <Outlet>,來處理我們常駐在畫面的navbar
// 我這裡將這些東西拆出來用Layout的component去做封裝,類似像mantine的app shell在處理
// 當然這裡也可以是需求將element內的component做layz loading的動作來提升FCP效能
const routes = [
{
path: "/",
element: <Layout />,
children: [
{ index: true, element: <Home /> },
{ path: "about", element: <About />},
{
path: "shop",
element: <Shop />,
children: [
{
path: "shirts",
element: <Shirts/>,
},
{
path: "shirts/:id",
element: <ShirtWid/>,
},
{
path: "pants",
element: <Pants />,
},
{
path: "pants/:id",
element: <PantWid />,
},
]
},
{
path: "contact",
element: <Contact />,
}
]
},
]
const RouteConf = () => {
const routeConfig = useRoutes(routes)
return routeConfig
}
export default RouteConf
步驟 4 — 回到App.tsx做修改如下:
import { FC } from "react"
import { BrowserRouter } from "react-router-dom"
import RouteConf from "./RouteConf"
// 全部交由RouteConf來進行路由管理
const App: FC = () => {
return (
<BrowserRouter>
<RouteConf/>
</BrowserRouter>
)
}
export default App
之後的資料夾結構可以參考我 github 連結的專案結構,或者你想使用 Next 的 route 結構就隨個人或團隊喜好決定,這裡我沒提及那些 hook 的使用,但我相信大家可以很輕鬆的在官網文件或是我 github 連結的教學,學到基本或更進階的應用。
路由真的沒有那麼複雜,使用 Next 框架的考量觀念也不應該只鎖定在 Router,尤其在新手階段還不清楚 React 的運作機制就跳去使用 Next 的全端框架,只會把簡單的問題複雜化,導致後續學習的頓挫感。
我是自學派的,自學東西的動機,必須建立在學這個東西能解決我現在問題,並且不會產生過多的副作用為主。
不然,等我學會了又多出更多問題,這頭都沒消化完全,那頭開始產生更多問題,只會更加雜亂。
先熟悉 CSR,再慢慢搞懂什麼情況下,需要使用不同渲染模式的作法來達到目的?
這樣的循序漸進你會比較清楚每個框架的思維邏輯。