课程:React18 系统精讲
章节:路由系统
讲师:阿莱克斯刘
课程内容:
如何从React Router V5 升级到 V6
1. 升级 react-router 包
npm install react-router-dom@[VERSION_NUMBER]
替换VERSION_NUMBER为我们要安装的版本,或者如果我们想要最新版本,则替换为“ latest ”, 如下所示:
npm install react-router-dom@6
或者
npm install react-router-dom@latest
2. 使用 Routes 替换 Switch
在 React Router v5 中,我们使用Switch组件包装路由,它可以确保每次只匹配的路由。但Switch组件在 React Router v6 中已经被废弃了,在React Router v6中我们使用Routes组件来替换Switch。
React Router v5:
import { BrowserRouter, Switch } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Switch>
{/* 定义路径 Route */}
</Switch>
</BrowserRouter>
);
}
export default App
React Router v6:
import { BrowserRouter, Routes } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
{/* 使用 Routes 代替 Switch*/}
{/* 定义路径 Route */}
</Routes>
</BrowserRouter>
);
}
export default App
3. 废弃 exact 属性
在 v5 中,如果给某个Route组件添加exact属性,那么路由将会进行精确匹配,而整个路由匹配过程是从上到下按顺序进行的。
而在 v6 中,我们将不再需要声明exact属性,路径模式匹配彻底改写,不再严格要求路径顺序,为我们的开发增加了极大的灵活性。
React Router v5:
<Switch>
{/* Route组件使用三种方式 */}
{/* 直接在component定义子页面 */}
<Route path="/page1" component={Page} />
{/* 通过嵌套子页面 */}
<Route path="/page2">
<Page id={2} />
</Route>
{/* 通过render函数渲染页面 */}
<Route path="/page3" render={(props) => <Page {...props} />} />
</Switch>
React Router v6:
<Routes>
<Route path="/page1" element={<Page />} />
<Route path="/page2" element={<Page id={2} />} />
</Routes>
4. Links 和 NavLinks
Link和NavLink组件仍然可以在V6中运行。
Link组件与 v5 基本一致
NavLink组件删除了activeClassName和activeStyle prop。
在 v6 中,我们现在可以使用一个函数来获取有关链接活动状态的信息。该函数的参数是一个具有属性的对象isActive。此属性在链接处于活动状态时为真,在非活动时为假。isActive的值允许我们使用条件表达式来指示活动样式或类名。
React Router v5:
import {NavLink} from “react-router-dom”
{/* … */}
<NavLink
to="/page1"
style={{ color: "red" }}
activeStyle={{ color: "blue" }}
activeClassName="active"
>
page1
</NavLink>
React Router v6:
<NavLink
to="/page1"
style={({ isActive }) => ({ color: isActive ? "red" : "blue" })}
className={({ isActive }) => `link${isActive ? " active" : ""}`}
>
page1
</NavLink>
5. Navigate替代Redirect
v5 的重定向组件 Redirect 将会在v6中被废弃,我们需要使用 Navigate组件来在 v6 中实现页面重定向。
React Router v5:
<Route path="/page1">
<Redirect to="/page2" />
</Route>
<Route path="/page3" component={Page} />
React Router v6:
<Route path="/page" element={<Navigate to="/page2" />} />;
<Route path="/page3" element={<Page />} />;
6. 嵌套路由
顾名思义,嵌套路由是放置在另一个路由中的路由,用于在子组件中呈现更具体的导航信息。
在 v6 中,引入了Outlet组件,用于指定我们希望嵌套信息显示在哪里。Outlet 组件不是必需的,但它使代码更清晰。
React Router v5:
import { useRouteMatch } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/touristRoute" component={TouristRoute} />
</Switch>
</BrowserRouter>
);
}
function TouristRoute() {
let match = useRouteMatch();
return (
<div>
<Switch>
{/* 匹配 “/touristRoute" */}
<Route path={`${match.path}`}>
<AllTouristRoute />
</Route>
{/* 匹配 /touristRoute/:id */}
<Route path={`${match.path}/:id`}>
<TouristRouteDetail />
</Route>
</Switch>
</div>
);
}
React Router v6:
import { Outlet } from "react-router-dom";
function App() {
return (
<Routes>
<Route path="/page" element={<Page />} />
<Route path="/touristRoute" element={<Order />}>
{/* 匹配 "/touristRoute/" */}
<Route path="/" element={<AllTouristRoute />} />
{/* 这里变成 "/touristRoute/:id" */}
<Route path="/:id" element={<TouristRouteDetail />} />
</Route>
</Routes>
);
}
function TouristRoute() {
return (
<Container>
<>
<div>TouristRoute</div>
</>
{/* 路由嵌套于此 */}
<Outlet />
</Container>
);
}
7. useHistory vs useNavigate
在 v6 中,useHistory 被废弃了,需要使用 useNavigate
React Router v5:
import { useHistory } from "react-router-dom";
function Product() {
const history = useHistory();
const handleClick = () => {
//这会将新路线推送到导航堆栈的顶部
history.push("/new-route");
//这会将当前路线替换为导航堆栈中的新路由
history.replace("/new-route");
};
return (
<div>
<button>点击我重定向到新路由</button>
</div>
);
}
React Router v6:
import { useNavigate } from "react-router-dom";
function Product() {
const navigate = useNavigate();
const handleClick = () => {
//这会将新路线推送到导航堆栈的顶部
navigate("/new-route");
//这会将当前路线替换为导航堆栈中的新路由
navigate("/new-route", { replace: true });
};
return (
<div>
<button>点击我重定向到新路由</button>
</div>
);
}
在 v6中,我们可以在导航堆栈上任意前进和后退。调用方法navigate(),参数传入正数,路由会向前移动;负数则后退。
// 前进1步
navigate(1)
// 前进2步
navigate(2)
// 后退1步
navigate(-1)
// 后退3步
navigate(-3)