乐趣区

关于react-router:从-React-Router-v5-过渡到-v6

React-routerreact 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 中的任何形式搁置咱们想要渲染的组件,而是对立将其作为elementprop 的值传递。

没有 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

LinkNavLink 组件依然能够运行在 V6。Link组件应用与在 v5 的时候放弃一样,但应用 NavLink 组件时,删除了 activeClassNameactiveStyle prop。在 v5 中,activeClassNameprop 用于在链接激活后主动将一些 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 中,useHistoryhook 被替换为useNavigatehook,并且咱们以不同的形式应用它。

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)中,useBlockerusePrompt 都不起作用。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 组件(双关语十分无意)😌。

    领有更杰出的编码体验🙌。

退出移动版