共计 5358 个字符,预计需要花费 14 分钟才能阅读完成。
React-router
是 react js
中路由的规范库。它容许 React
应用程序的用户在应用程序的不同局部(组件)之间挪动。
react-router
团队 发表将 在 2021 年底公布 react-router 版本 6 (v6)
的稳固版本,但因为一些重大的 API 更改,从 react-router
版本 5 (v5)
切换到 v6
可能会很艰难. 在本文中,咱们将介绍 v6 中的新性能以及如何将现有的 React 我的项目从 v5 降级到 v6。
要在咱们的应用程序中降级 react-router
包的版本,咱们导航到我的项目文件夹并运行
npm install react-router-dom@[VERSION_NUMBER]
替换 VERSION_NUMBER
为咱们要装置的版本,或者如果咱们想要最新版本,则替换为“latest”,如下所示:
npm install react-router-dom@6
或者
npm install react-router-dom@latest
请留神,咱们必须连贯到互联网能力实现装置,否则装置将失败。另外,请确保我的项目中的 react 版本是 v16.8 或更高版本
,因为 react-router v6
重大依赖于 react v16.8
最后反对的钩子
Switch 被替换为 Routes
v5
时代的第一个被代替的是 Switch 组件
。该Switch
组件用于包装咱们的路由,它确保 每次只加载一个匹配的路由 。但这在 v6 中不再存在。咱们应用Routes
组件来替换 Switch
。请留神,咱们依然须要导入BrowserRouter
包装咱们的应用程序,就像在 v5 中所做的那样。
在 v5 中,咱们是这样做:
import {BrowserRouter, Switch} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<div className="App">
<Switch>
{" "}
{/* 路由 Route 在此定义 */}
</Switch>
</div>
</BrowserRouter>
);
}
export default App
但在 v6 中,咱们将这样做
import {BrowserRouter, Routes} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<div className="App">
<Routes>
{" "}
{/* Switch 会被改成 Routes */}
{/* 路由 Route 在此定义 */}
</Routes>
</div>
</BrowserRouter>
);
}
export default App
Route 组件应用更新
只管该 Route 组件在 v6
中依然保留一个地位,但咱们定义它的应用形式与咱们在 v5
中的形式不同。咱们将不再以 v5
中的任何形式搁置咱们想要渲染的组件,而是对立将其作为element
prop 的值传递。
没有 exact 配置
在 v5
中,不增加 exact
作为 Route 组件
的props
的话,如果 URL 以 path 关键字结尾,则门路将匹配,因为匹配过程是 从上到下的程序 。但在 v6 中,咱们将不再须要该exact
配置,因为门路模式匹配算法已更改,并且当初更加加强。
在 v5 中,咱们这样做了:
<Switch>
{/* 三种 Route 组件应用定义 */}
<Route path="/signup" component={Product} />
{/* 或 */}
{/* 这个办法容许咱们将 props 传递给渲染的组件 */}
<Route path="/games">
<Product id={2} />
</Route>
{/* 或是通过 render 函数 */}
<Route path="/games" render={(props) => <Product {...props} />} />
</Switch>
在 v6 中,
<Routes>
{" "}
<Route path="/games" element={<Product />} />
{/* 带有 props 的渲染组件 */}
<Route path="/movies" element={<Product id={200} category="shirt" />} />
</Routes>
Links 和 NavLinks
Link
和 NavLink
组件依然能够运行在 V6。Link
组件应用与在 v5 的时候放弃一样,但应用 NavLink
组件时,删除了 activeClassName
和activeStyle
prop。在 v5 中,activeClassName
prop 用于在链接激活后主动将一些 CSS
类利用于链接,同时 activeStyle
容许咱们在链接激活时向链接增加外部款式。
然而在 v6 中,咱们当初能够应用一个函数来获取无关链接活动状态的信息。该函数的参数是一个具备属性的对象 isActive
。此属性在链接处于活动状态时为 真,在非流动时为 假。isActive
的值容许咱们应用条件表达式来批示流动款式或类名。
在 v5 中,咱们这样做了:
import {NavLink} from“react-router-dom”{/* … */}
<NavLink
to="/product"
style={{color: "#689"}}
activeStyle={{color: "#3072c9"}}
className="nav_link"
activeClassName="active"
>
Products
</NavLink>
但在 v6 中,咱们将这样做:
<NavLink
to="/product"
style={({isActive}) => ({color: isActive ? "#3072c9" : "#689"})}
className={({isActive}) => `link${isActive ? "active" : ""}`}
>
Product
</NavLink>
Navigate 代替 Redirect
在 v5 中,咱们应用该 Redirect
组件将一个页面带到另一个页面,但它不再从 v6
中的 react-router-dom
导出。它已被 Navigate
组件替换。
在 v5 中,咱们这样做了:
<Route path="/faq">
<Redirect to="/about" />
</Route>
<Route path="/about" component={About} />
但在 v6 中,咱们将这样做:
<Route path="/games" element={<Navigate to="/about" />} />;
<Route path="/games" element={<About />} />;
须要留神的是,如果咱们只是依照 Navigate 下面代码片段中的形式增加组件,它只会将导航到该门路的导航推送到导航堆栈中,然而如果咱们打算用新页面替换以后页面,咱们将 replace 属性增加到 Navigate 组件中,如下所示:
<Route path=”/games” element={<Navigate replace to=”/about” />} />;
嵌套路由
顾名思义,嵌套路由是搁置在另一个路由中的路由。它们用于在子组件中出现更具体的信息。在 v6 中,咱们将嵌套路由搁置为父路由的子路由。而后咱们引入 Outlet
组件,它是从渲染组件中的 react-router-dom
导出的,用于指定咱们心愿嵌套信息显示在哪里。Outlet
组件不是必须的,但它使代码更清晰。
在 v5 中,咱们这样做了:
import {useRouteMatch} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/about" component={About} />
<Route path="/product" component={Product} />
</Switch>
</BrowserRouter>
);
}
function Product() {let match = useRouteMatch();
return (
<div>
<Switch>
{/* match.path 返回父路由中指定的门路。在这种状况下,它是“/product" */}
<Route path={`${match.path}`}>
<AllProducts />
</Route>
{/* 匹配 /product/:id */}
<Route path={`${match.path}/:id`}>
<ProductDetail />
</Route>
</Switch>
</div>
);
}
在 v6 中,咱们这样做:
import {Outlet} from "react-router-dom";
function App() {
return (
<Routes>
<Route path="/about" element={<About />} />
<Route path="/product" element={<Product />}>
{/* 这里嵌套路由的门路是绝对于父路由的门路的。*/}
{/* 这里变成 "/product/" */}
<Route path="/" element={<AllProducts />} />
{/* 这里变成 "/product/:id" */}
<Route path="/:id" element={<ProductDetail />} />
</Route>
</Routes>
);
}
function Product() {
return (
<Container>
<>
<div>Product</div>
{/* 父组件的其余内容 */}
</>
{/* 这是嵌套信息开始的中央 */}
<Outlet />
</Container>
);
}
程序化导航
当用户因门路上产生的事件(例如单击按钮、API 申请实现等 )而被重定向时,就会产生程序化导航。在 v5 中,咱们能够应用useHistory
钩子来执行以下操作:
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>
);
}
然而在 v6 中,useHistory
hook 被替换为useNavigate
hook,并且咱们以不同的形式应用它。
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>
);
}
一件很酷的事件是咱们能够在导航堆栈上任意后退和后退。通过应用负数作为上述参数navigate()
,路由会向前挪动该步数。正数向后做同样的事件
// Goes forward
navigate(1)
// Goes forward twice
navigate(2)
// Goes backward
navigate(-1)
// Goes backward three times
navigate(-3)
删除 Prompt 组件
Prompt 如果有未保留的更改,v5 中的组件可避免意外来到页面。然而 react-router
团队并没有将它蕴含在 v6
中,也没有代替计划。因而,如果你须要该性能,你能够手动实现它或返回到 v5。
除了不包含 Prompt
在以后版本(v6)中,useBlocker
和 usePrompt
都不起作用。react-router
团队尽管在官网文档中示意,他们目前正在致力将其增加回 v6
,但不是针对 6.x 的第一个稳固版本。
概括
让咱们强调一下咱们所经验的变动。
- Switch 组件替换为 Routes 组件。
- 如何搁置 Route 的渲染组件的更改。
- 路由中没有 exact。
- activeClassName 和 activeStyle 不存在于 NavLink 组件了.
- 咱们能够通过函数回调拜访 NavLink 组件的 isActive 状态。
- Redirect 组件已替换为 Navigate 组件。
- 实现嵌套路由的一种更时尚的形式。
- 没有 Prompt 组件
总之,如果你还没有筹备好从 v5 或任何其余版本切换到 v6,你能够持续应用它装置以前的版本。
npm install react-router-dom@[VERSION_NUMBER]
然而,你将错过 v6 附带的一些好货色,包含但不限于:
- 加强的门路模式匹配算法。
- 依据 Bundlephobia,体积大小缩小了 60%
-
我置信咱们可能胜利地切换到 react-router v6 并停止使用 Switch 组件(双关语十分无意)😌。
领有更杰出的编码体验🙌。