react-router-dom5升级到6

前言

升级前版本为5.1.2

下载与运行

下载

复制代码
npm install react-router-dom@6

运行

运行发现报错:

将node_modules删除,重新执行npm i即可

运行发现如下报错

这是因为之前有引用react-router-dom.min,v6中取消了该文件,所以未找到文件导致报错。

将引用变为react-router-dom即可解决。

再次运行发现如下报错:

这是因为react-router-dom6取消了withRouter,如果想要获取路由地址,需要使用useLocation

变为

再次运行发现如下报错:

按照官网进行如下修改:

Switch 被替换为 Routes

v5 时代的第一个被替代的是Switch组件。该Switch组件用于包装我们的路由,它确保每次只加载一个匹配的路由 。但这在 v6 中不再存在。我们使用Routes组件来替换Switch。请注意,我们仍然需要导入BrowserRouter包装我们的应用程序,就像在 v5 中所做的那样。

在 v5 中,我们是这样做:

javascript 复制代码
import { BrowserRouter, Switch } from "react-router-dom";

function App() {
    return (
        <BrowserRouter>
            <div className="App">
                <Switch>
                    {/* 路由Route在此定义 */}
                </Switch>
            </div>
        </BrowserRouter>
    );
}
export default App

但在 v6 中,我们将这样做

javascript 复制代码
import { BrowserRouter, Routes } from "react-router-dom";

function App() {
    return (
        <BrowserRouter>
            <div className="App">
                <Routes>
                    {/* Switch 会被改成 Routes */}
                    {/* 路由Route在此定义 */}
                </Routes>
            </div>
        </BrowserRouter>
    );
}

export default App

注意:v5的Switch中可以包含非Route元素,但Routes中只能存在Route,否则会报错。

Route组件使用更新

尽管该Route组件在 v6 中仍然保留一个位置,但我们定义它的使用方式与我们在 v5 中的方式不同。我们将不再以 v5 中的任何方式放置我们想要渲染的组件,而是统一将其作为elementprop的值传递。

没有exact配置

v5 中,不添加exact作为Route组件props的话,如果 URL 以 path 关键字开头,则路径将匹配,因为匹配过程是从上到下的顺序 。但在 v6 中,我们将不再需要该exact配置,因为路径模式匹配算法已更改,并且现在更加增强。

在 v5 中,我们这样做了:

javascript 复制代码
<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 中,

javascript 复制代码
<Routes>
   {" "}
   <Route path="/games" element={<Product />} />
   {/* 带有props的渲染组件 */}
   <Route path="/movies" element={<Product id={200} category="shirt" />} />
</Routes>

LinkNavLink组件仍然可以运行在V6。Link组件使用与在 v5 的时候保持一样,但使用NavLink组件时,删除了activeClassNameactiveStyle prop。在 v5 中,activeClassNameprop 用于在链接激活后自动将一些 CSS 类应用于链接,同时activeStyle允许我们在链接激活时向链接添加内部样式。

但是在 v6 中,现在可以使用一个函数来获取有关链接活动状态的信息。该函数的参数是一个具有属性的对象isActive。此属性在链接处于活动状态时为 ,在非活动时为isActive的值允许我们使用条件表达式来指示活动样式或类名。

在 v5 中,

javascript 复制代码
import {NavLink} from "react-router-dom"

{/* ... */}
<NavLink
   to="/product"
   style={{ color: "#689" }}
   activeStyle={{ color: "#3072c9" }}
   className="nav_link"
   activeClassName="active"
>
   Products
</NavLink>

但在 v6 中,我们将这样做:

javascript 复制代码
<NavLink
   to="/product"
   style={({ isActive }) => ({ color: isActive ? "#3072c9" : "#689" })}
   className={({ isActive }) => `link${isActive ? " active" : ""}`}
>
   Product
</NavLink>

在 v5 中,使用该Redirect组件将一个页面带到另一个页面,但它不再从 v6 中的 react-router-dom 导出。它已被Navigate组件替换。

在 v5 中,

javascript 复制代码
<Route path="/faq">
   <Redirect to="/about" />
</Route>
<Route path="/about" component={About} />

但在 v6 中,

javascript 复制代码
<Route path="/games" element={<Navigate to="/about" />} />;
<Route path="/games" element={<About />} />;

需要注意的是,如果只是按照Navigate上面代码片段中的方式添加组件,它只会将导航到该路径的导航推送到导航堆栈中,但是如果我们打算用新页面替换当前页面,我们将 replace 属性添加到Navigate组件中,如下所示:

javascript 复制代码
<Route path="/games" element={<Navigate replace to="/about" />} />;

嵌套路由

顾名思义,嵌套路由是放置在另一个路由中的路由。它们用于在子组件中呈现更具体的信息。在 v6 中,将嵌套路由放置为父路由的子路由。然后引入Outlet组件,它是从渲染组件中的 react-router-dom 导出的,用于指定希望嵌套信息显示在哪里。Outlet 组件不是必需的,但它使代码更清晰。

在 v5 中,

javascript 复制代码
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 中,

javascript 复制代码
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>
   );
}

useNavigate代替useHistory

当用户因路径上发生的事件(例如单击按钮、API 请求完成等 )而被重定向时,就会发生程序化导航。在 v5 中,可以使用useHistory钩子来执行以下操作:

javascript 复制代码
import { useHistory } from "react-router-dom";

function Product() {
   const history = useHistory();

   const handleClick = () => {
       //这会将新路线推送到导航堆栈的顶部
       history.push("/new-route");
       history.push({pathname:"/new-route",state:{p1:xxx});  // 传参

       //这会将当前路线替换为导航堆栈中的新路由
       history.replace("/new-route");
   };

   return (
       <div>
           <button>点击我重定向到新路由</button>
       </div>
   );
}

但是在 v6 中,useHistoryhook 被替换为useNavigatehook,并且以不同的方式使用它。

javascript 复制代码
import { useNavigate } from "react-router-dom";

function Product() {
   const navigate = useNavigate();

   const handleClick = () => {
       //这会将新路线推送到导航堆栈的顶部
       navigate("/new-route");
	   navigate("/new-route",{state:{p1:xxx}});  // 传参

       //这会将当前路线替换为导航堆栈中的新路由
       navigate("/new-route", { replace: true });
   };

   return (
       <div>
           <button>点击我重定向到新路由</button>
       </div>
   );
}

一件很酷的事情是以在导航堆栈上任意前进和后退。通过使用正数作为上述参数navigate(),路由会向前移动该步数。负数向后做同样的事情

javascript 复制代码
// 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)中,useBlockerusePrompt都不起作用。react-router 团队虽然在官方文档中表示,他们目前正在努力将其添加回 v6,但不是针对 6.x 的第一个稳定版本。

注意

react-router-dom5的Switch可以嵌套Redirect

但react-router-dom6的Routes中只可以存在Route和Route.Fragment

v5的Router写法,需要利用history

js 复制代码
import { createBrowserHistory } from "history"
const customHistory = createBrowserHistory()

const Root = () => {
	return (
		<Router history={customHistory}>
				......
		</Router>
	)
}

v6直接更改路由引入方式即可

js 复制代码
import { BrowserRouter } from "react-router-dom"

const Root = () => {
	return (
		<BrowserRouter>
				......
		</BrowserRouter>
	)
}
相关推荐
L耀早睡17 分钟前
mapreduce打包运行
大数据·前端·spark·mapreduce
HouGISer30 分钟前
副业小程序YUERGS,从开发到变现
前端·小程序
outstanding木槿36 分钟前
react中安装依赖时的问题 【集合】
前端·javascript·react.js·node.js
霸王蟹1 小时前
React中useState中更新是同步的还是异步的?
前端·javascript·笔记·学习·react.js·前端框架
霸王蟹1 小时前
React Hooks 必须在组件最顶层调用的原因解析
前端·javascript·笔记·学习·react.js
专注VB编程开发20年1 小时前
asp.net IHttpHandler 对分块传输编码的支持,IIs web服务器后端技术
服务器·前端·asp.net
爱分享的程序员2 小时前
全栈项目搭建指南:Nuxt.js + Node.js + MongoDB
前端
隐含3 小时前
webpack打包,把png,jpg等文件按照在src目录结构下的存储方式打包出来。解决同一命名的图片资源在打包之后,重复命名的图片就剩下一个图片了。
前端·webpack·node.js
lightYouUp3 小时前
windows系统中下载好node无法使用npm
前端·npm·node.js
Dontla3 小时前
npm cross-env工具包介绍(跨平台环境变量设置工具)
前端·npm·node.js