今天要來介紹的是react-router-dom這個套件,它用來模擬換頁的一套路由工具,讓我們可以使用它來完成Single Page Application(SPA)中變換路徑達成切換頁面的功能。
npm install react-router-dom
createBrowserRouter
使用createBrowserRouter
建立路由的規範。path
為路徑element
為在這個路徑的時候要呈現的內容,也可以是React元件
import {
createBrowserRouter
} from "react-router-dom";
const router = createBrowserRouter([
{
// 在根目錄呈現的是<div>Hello world!</div>
path: "/",
element: <div>Hello world!</div>,
},
{
// 在/deom路徑呈現的是<div>demo</div>
path: "/demo",
element: <div>demo</div>,
},
]);
在root的地方包一層<RouterProvider>
並帶入*createBrowserRouter
建立的路由規範,被包住的<App />
底下都可以操作路徑等的路由功能。
import {
RouterProvider
} from "react-router-dom";
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<RouterProvider router={router}>
<App />
</RouterProvider>
</React.StrictMode>,
)
<BrowserRouter>
也可以使用<BrowserRouter>
來建立路由規則,使用<BrowserRouter />
包著<Routes>
再包著帶入path和element的<Route>
import React from 'react'
import ReactDOM from 'react-dom/client'
import {
BrowserRouter,
Route,
Routes
} from "react-router-dom";
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<BrowserRouter basename="/">
<Routes>
<Route path="/" element={<App />} />
<Route path="/demo" element={<Demo />} />
<Route path="/artical/:articalID" element={<Artical />} />
</Routes>
</BrowserRouter>
</React.StrictMode>,
)
兩種用法大同小異就看習慣哪種
在元件裡也可以使用<Link>
這個react-router-dom提供的元件來切換路徑
import { Link } from "react-router-dom";
export default function App() {
return <Link to={`/demo`}>DEMO PAGE</Link>
}
在程式理切換路徑
使用useNavigate
回傳的function,帶入路徑可以用程式的方式切換路徑
import { Link, useNavigate } from "react-router-dom";
export default function Demo() {
const navigate = useNavigate();
return <button onClick={() => {
navigate("/");
}}>TO Home PAge </button>
}
直接return<Navigate />
當元件return<Navigate />
,會在渲染到這裡時導頁至參數to的路徑
import { Navigate } from "react-router-dom";
function App() {
return <Navigate to="/" />;
}
在path參數的路徑使用分號+變數名稱,就可以使用動態路由,路徑會是/artical/任意值,例如/artical/abc
{
path: '/artical/:articalID',
element: <Artical />
}
使用useParams
抓取動態路由的值,如果路徑為/artical/abc,下面範例的articalID就會是abc
import { useParams } from 'react-router-dom';
export default function Artical() {
const { articalID } = useParams();
return <div>{articalID}</div>
}
我們可以在路由裡設定,根據路徑讓父層的元件裡面插入另一塊元件
createBrowserRouter
建立在path為/demo的物件新增一個children參數,裡面放入要呈現的內容
import {
createBrowserRouter,
Outlet,
} from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <App />,
},
{
path: "/demo",
element: <Demo />,
children: [
{
path: "id",
element: <div>demo children</div>,
},
],
},
]);
在<Demo />
元件裡面放入<Outlet />
,在config children裡的element將會呈現在<Outlet />
的位置
import {
Outlet,
} from "react-router-dom";
export default function Demo() {
const navigate = useNavigate();
return <>
<div> demo page </div>
<Outlet />
</>
}
<*BrowserRouter>
建立*在demo的<Route>
底下建立一個children的<Route>
<BrowserRouter basename="/">
<Routes>
<Route path="/" element={<App />} />
<Route path="/demo" element={<Demo />}>
<Route path="id" element={<div>demo children</div>} />
</Route>
</Routes>
</BrowserRouter>
我們在有些頁面會需要登入或是驗證才可以瀏覽頁面,我們可以在路由要瀏覽的元件外包一層元件,這個元件可以用來檢查有沒有登入或是驗證,沒有登入的話就會把使用者導到其他頁面,如果有登入就可以瀏覽底下的children元件。
這邊的範例使用Props來傳入loginStatus
,但是也可以用其他方式,像是在元件裡面抓取cookie的資料等方式來判斷有沒有登入。
import { Navigate } from "react-router-dom";
export default function RouterGuard({children, loginStatus}) {
if (!loginStatus) {
return <Navigate to="/" replace />; //沒有登入就會導到首頁
}
return children
}
路由設定
在<Private />
的父層包裹<RouterGuard >
<BrowserRouter basename="/">
<Routes>
<Route path="/" element={<App />} />
<Route path='/private' element={
<RouterGuard loginStatus={true}>
<Private />
</RouterGuard>
} />
</Routes>
</BrowserRouter>
或
const router = createBrowserRouter([
{
path: "/",
element: <App />,
},
{
path: 'private',
element: <RouterGuard loginStatus={true}>
<Private />
</RouterGuard>
},
https://reactrouter.com/en/main
https://www.robinwieruch.de/react-router-private-routes/