[react] React Router DOM v5 與 v6 之差異介紹
Configuring Routes
跟前幾個版本差不多,在用 Router 的時候必須要先引入 BroswerRouter 來包住整個 component。
import Home from "./components/Home";import About from "./components/About";import { BrowserRouter as Router, Routes, Route } from "react-router-dom";function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </Router> );}export default App;
Routes:跟前版本的 Switch 的功用差不多,在 Routes 裡面的 component 都必須定義 Route,不然會報錯。
Route:之前的使用方法是在 Route 上使用"component"屬性,現在改為 element 屬性,path 的設定一樣。
Link
如果要到 Route 定義的 path,則可以使用 Link Component,使用的方法也非常簡單,只要在 Link 加上 to 屬性指向到 path 就好。
import Home from "./components/Home";import About from "./components/About";import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";function App() { return ( <Router> <nav> <Link to="/">Home</Link>|<Link to="/about">About</Link> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </Router> );}export default App;
exact
之前的版本在定義 Route 的時候會發生一個情況,假如網頁的 url 是 localhost:3000/about,那假如我在 Router 的定義如下,則會連同 "/" 一起匹配到,所以都會在 path 是 "/" 的加上 exact,意思就是嚴格匹配,而在 v6 已經內建嚴格匹配了,所以不需要特別做設定。
<Router> <Route path={"/"} exact component={Home} /> <Route path={"/about"} component={About} /></Router>
NavLink
v5 版本的 activeClassName 已經被移除了,最新版的 className 會自帶 isActive 的參數,所以直接用該參數來判斷是否 active 就好。
<NavLink className={(navData) => (navData.isActive ? "active" : "")} to="/about"> About</NavLink>
useNavigate
取代了 v5 的 useHistory,使用 useNavigate 可以很輕鬆的跳轉到其他 Route path,當然,也可以使用 Link Component,但就不能在 function 裡面去做使用。
在舊版的 useHistory 當我們網頁需要 回到上一頁或下一頁時會使用 history.goBack()或 history.goForward()
而在新版的 navigate 可以直接使用數字來代替
import React from "react";import { useNavigate } from "react-router";const About = () => { const navigate = useNavigate(); return ( <div> <h1>ABOUT PAGE</h1> <button onClick={() => navigate("/")}>Go To Home Page</button> <button onClick={() => navigate(1)}>1 step forward</button> <button onClick={() => navigate(-1)}>1 step back</button> </div> );};export default About;
useParams
假使我們在一個頁面需要透過 url 的參數來取得資料, 例如:localhost:3000/profile/wei 、 localhost:3000/profile/yun
我們想要取得 url 後面的 wei 跟 yun,這時候可以透過 useParams 來幫助我們,但在 Route 的部分也要設定。
import "./App.css";import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";import Home from "./components/Home";import About from "./components/About";import Profile from "./components/Profile";function App() { return ( <Router> <nav> <Link to="/">Home</Link>|<Link to="/about">About</Link> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/profile/:name" element={<Profile />} /> //加上 /:name </Routes> </Router> );}export default App;
import React from "react";import { useParams } from "react-router";const Profile = () => { const { name } = useParams(); //要跟Route設定的參數名稱一樣 return ( <div> <h1>PROFILE PAGE</h1> <h2>Hello {name}</h2> </div> );};export default Profile;
現在在 url 要是輸入 localhost:3000/profile/wei 會看到以下畫面
useSearchParams
在網址如果有帶一些參數,則可以使用 useSearchParams 來取得該參數的值。
假設網址是:localhost:3000/profile/wei?sortby=id
import React from "react";import { useParams } from "react-router";import { useSearchParams } from "react-router-dom";const Profile = () => { const { name } = useParams(); let [searchParams] = useSearchParams(); console.log(searchParams.get("sortby")); //output : id return ( <div> <h1>PROFILE PAGE</h1> <h2>Hello {name}</h2> </div> );};export default Profile;
假設網址是:localhost:3000/profile/wei?test=1&test=2
要是參數有兩個同名稱但不同值的話,可以使用 getAll。
import React from "react";import { useParams } from "react-router";import { useSearchParams } from "react-router-dom";const Profile = () => { const { name } = useParams(); let [searchParams] = useSearchParams(); console.log(searchParams.getAll("test")); //output : ["1","2"] return ( <div> <h1>PROFILE PAGE</h1> <h2>Hello {name}</h2> </div> );};export default Profile;
useRoutes
404 頁面
假設今天在 Routes 底下匹配不到 path,會出現空白頁面,這時候我們可以自訂 Error Component,當匹配不到時就會跳到該頁面。
App.js
import Home from "./components/Home";import About from "./components/About";import Error from "./components/Error";import { BrowserRouter as Router, Routes, Route } from "react-router-dom";function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="*" element={<Error />} /> </Routes> </Router> );}export default App;
在 path 的地方加上"*",意思就是 Routes 底下匹配不到的時候才會去匹配該 path,這邊要注意的是path="*"的 Route 必須放在最底下,因為 Routes 匹配是有優先順序的。