跳至主要内容

[react] React Router DOM v5 與 v6 之差異介紹

React Router Docs

Configuring Routes

跟前幾個版本差不多,在用 Router 的時候必須要先引入 BroswerRouter 來包住整個 component。

App.js
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 的設定一樣。

如果要到 Route 定義的 path,則可以使用 Link Component,使用的方法也非常簡單,只要在 Link 加上 to 屬性指向到 path 就好。

App.js
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 已經內建嚴格匹配了,所以不需要特別做設定。

舊版本(v5)
<Router>
<Route path={"/"} exact component={Home} />
<Route path={"/about"} component={About} />
</Router>

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 可以直接使用數字來代替

About.js
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 的部分也要設定。

App.js
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;
Profile.js
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

Profile.js
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。

Profile.js
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

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 匹配是有優先順序的。