【React】React router (v6)
在學 React 的時候,一定會接觸到 React router 來建立路由。在沒有 Next.js 的 Page router 及 App router 以前,React router 是最常用的路由套件。在去年 2022/09/14 發佈了 v6.4 版本,從這個版本開始,新增了很多新功能,主要集中在 API fetching、Data loading 等功能上,而要使用這些功能必須把原本的 BrowserRouter
換成 createBrowserRouter
API 及 <RouterProvider/>
元件,這一篇就來介紹 v6 的新功能及用法。
createBrowserRouter + RouterProvider
creactBrowserRouter
+ <RouterProvider/>
取代了原本的 <BrowserRouter/>
元件,讓路由的結構能更好閱讀及管理。creactBrowserRouter
可以接受以物件形式組成的 Nest Router Config,而在引入根元件時,只要使用 <RouterProvider />
再把 creactBrowserRouter
API 產生的 router 傳入就可以了。
物件形式:
import { createBrowserRouter } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
children: [
{
path: "about",
element: <About />,
},
],
},
]);
export default router;
除了物件形式,也可以接受使用像原本的 Nest Component 的結構,需要另外使用 createRoutesFromElements
來包裹:
import {
createBrowserRouter,
createRoutesFromElements,
Route,
} from "react-router-dom";
const router = createBrowserRouter(
createRoutesFromElements(
<Route path='/' element={<Home />}>
<Route path='about' element={<About />} />
</Route>
)
);
export default router;
使用 <RouterProvider/>
:
import { RouterProvider } from "react-router-dom";
import router from "./router";
function App() {
return <RouterProvider router={router} />;
}
Data Loading
以往在進到某個頁面,需要 call API 來渲染畫面,通常會在 useEffect
中 call API,然後把資料存在 state 中,再用 state 來渲染畫面。但是這樣的寫法會有幾個問題:
- 進到頁面時,畫面會先渲染一次,然後 call API,再渲染一次
- 如果 API call 失敗,畫面會一直停留在 loading 狀態
所以在設計的時候都會需要建立幾個 flag 來控制,例如 isLoading
、isError
、data
等等,這樣的寫法會讓程式碼變得很冗長。如果有使用像 TanStack Query、RTK Query 等套件,可以幫助我們處理這些問題。不過如果純粹想在 Router 切換時去管理 Data Fetching,就可以使用 v6 的 loader 功能。
首先建立一個 fetchData()
函式:
export const fetchData = (url) => {
const res = await fetch(url);
const data = await res.json();
return data;
};
傳入 loader 參數中:
import { createBrowserRouter } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
children: [
{
path: "about",
element: <About />,
loader: () => fetchData("API_URL"),
},
],
},
]);
這樣就可以在進到 <About/>
頁面時,自動 call API 等待資料回傳後才會渲染畫面。react-router-dom 也提供了 useLoaderData
的 hook,可以在頁面中取得回傳的 data:
import { useLoaderData } from "react-router-dom";
const About = () => {
const data = useLoaderData();
return <div>{JSON.stringify(data)}</div>;
};
export default About;