在 2021 年 11 月初,React Router 正式释出 v6 版本,身为 React 开发者已经按捺不住好奇心,想看看这个版本究竟增加了什麽功能?修改了什麽语法?因此就有了这篇文章的诞生。而在这篇文章中,我会介绍 v6 的一些新功能和 v5 有哪些地方不同。
v5:
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/topics">
<Topics />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
v6:
<Routes>
<Route path="/about" element={<About />} />
<Route path="/topics" element={<Topics />} />
<Route path="/" element={<Home />} />
</Routes>
在过去,需透过 exact 设定完全符合 url 时才会显现指定的元件内容,现在 Router 会抓取最相近的 url 去呈现对应的元件。
<Routes>
<Route path="/about" element={<About />} />
<Route path="/topics" element={<Topics />} />
<Route path="/topics/:topic" element={<SpecTopics />} />
<Route path="/" element={<Home />} />
</Routes>
在 React Router v5 的官网有提到 activeClassName 被移除,v6 直接用 className 去判定即可。
<NavLink className={(navData) => navData.isActive ? "active" : "" } to="/about" />
之前的版本需要搭配 useRouteMatch 去组出巢状路由,现在可以直接写上想要的子路由上去。
v5:
export default function Topics() {
let match = useRouteMatch();
console.log(match);
return (
<div>
<ul>
<li>
<Link to={`${match.url}/components`}>Components</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>Props v. State</Link>
</li>
</ul>
<Switch>
<Route path={`${match.path}/:topicId`}>
<Topic />
</Route>
<Route path={match.path}>
<h3>Please select a topic.</h3>
</Route>
</Switch>
</div>
);
}
v6:
export default function Topics() {
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to="components">Components</Link>
</li>
<li>
<Link to="props-v-state">Props v. State</Link>
</li>
</ul>
<Routes>
<Route path=":topicId" element={<Topic />} />
<Route path="*" element={<h3>Please select a topic.</h3>} />
</Routes>
</div>
);
}
另外在 path 有没有加上 '/' 结果都是一样的:
// 路由为 `/hobby/favorite`
<Route
path="favorite"
element={<FavoriteHobbyListBody />}
/>
// 路由也为 `/hobby/favorite`
<Route
path="/favorite"
element={<FavoriteHobbyListBody />}
/>
在 Dashboard 元件内部,会根据路由 /messages
或 /tasks
在 <Outlet />
的地方呈现对应的元件 <DashboardMessages />
or <DashboardTasks>
。
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
{/* This element will render either <DashboardMessages> when the URL is
"/messages", <DashboardTasks> at "/tasks", or null if it is "/"
*/}
<Outlet />
</div>
);
}
function App() {
return (
<Routes>
<Route path="/" element={<Dashboard />}>
<Route
path="messages"
element={<DashboardMessages />}
/>
<Route path="tasks" element={<DashboardTasks />} />
</Route>
</Routes>
);
}
useNavigate 的第一个参数可以是路由或是数字,代表前进或回去的页数。
v5:
import { useHistory } from "react-router-dom";
const News = () => {
let history = useHistory();
return (
<>
<button onClick={()=> history.push("/home")}>Home</button>
</>
);
}
v6:
import { useNavigate } from "react-router-dom";
const News = () => {
let navigate = useNavigate();
return (
<>
<button onClick={()=> navigate('/home')}>Home</button>
</>
);
}
v5:
import { useHistory } from "react-router-dom";
function Exchanges() {
const { go, goBack, goForward } = useHistory();
return (
<>
<button onClick={() => go(-2)}>
2 steps back
</button>
<button onClick={goBack}>1 step back</button>
<button onClick={goForward}>1 step forward</button>
<button onClick={() => go(2)}>
2 steps forward
</button>
</>
);
}
v6:
import { useNavigate } from "react-router-dom";
function Exchanges() {
const navigate = useNavigate();
return (
<>
<button onClick={() => navigate(-2)}>
2 steps back
</button>
<button onClick={() => navigate(-1)}>1 step back</button>
<button onClick={() => navigate(1)}>
1 step forward
</button>
<button onClick={() => navigate(2)}>
2 steps forward
</button>
</>
);
}
import React from "react";
import { useRoutes } from "react-router-dom";
const App = () => {
let element = useRoutes([
{
path: "/",
element: <Dashboard />,
children: [
{
path: "messages",
element: <DashboardMessages />
},
{ path: "tasks", element: <DashboardTasks /> }
]
},
{ path: "team", element: <AboutPage /> }
]);
return element;
}
除了上述几点之外,当然还有其他的变更,像是 React Router v6 整个 bundle size 缩小,更加轻量,不过以上就举比较常用的几点来说明,想了解更深入可以点击我推荐的 youtube 影片或是到官网去阅读文件罗!
最後,放上在铁人赛 Day19 文章中介绍 React Router v5 的范例程序码和修改後的 v6 版本程序码范例提供给读者做比较,不过范例中并没有将文中的全部功能都使用上去,读者可以自行练习看看哩!
v5 版本 codesandbox 范例
v6 版本 codesandbox 范例
今年的疫情蛮严重的,希望大家都过得安好, 希望疫情快点过去,能回到一些线下技术聚会的时光~ 今天目标...
【前言】 本系列为个人前端学习之路的学习笔记,在过往的学习过程中累积了很多笔记,如今想藉着IT邦帮忙...
今天我们来写一个简单的form来当作测试吧,首先我们刻出一个简单的画面 const App: FC ...
现在,基於我们现有的初始对话流与打造完成的语音应用程序。 来试着让它变得更好! 现在我们进入设计对...
ㄟ ,那个新出来的工具好酷喔 TeamsCity 和 Azure DevOps 好像很潮 拜托,G...