3
头图

React-router is the standard library for routes in react js It allows React application to move between different parts (components) of the application.

react-router team announced a stable release of react-router version 6 (v6) by the end of 2021, but switching react-router version 5 (v5) v6 may be difficult due to some major API changes. In this article, we will cover and how to upgrade an existing React project from v5 to v6 .

react-router package in our application, we navigate to the project folder and run

npm install react-router-dom@[VERSION_NUMBER]

Replace VERSION_NUMBER with the version we want to install, or "latest" if we want the latest version, like this:

npm install react-router-dom@6

or

npm install react-router-dom@latest

Note that we must be connected to the internet to complete the installation, otherwise the installation will fail. Also, please make sure that the react version in your project is v16.8 or higher, because react-router v6 relies heavily on react v16.8 originally supported by 061e0f5531cc00

Switch was replaced with Routes

The first to be replaced in the v5 Switch assembly. The Switch component is used to wrap our route, it ensures that only loads one matching route . But this no longer exists in v6. We use the Routes assembly to replace the Switch . Note that we still need to import BrowserRouter wrap our application, as we did in v5.

In v5, we do this:

import { BrowserRouter, Switch } from "react-router-dom";

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

but in v6 we will do

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 component use update

Although this Route component v6 , we define it to be used differently than we did in v5 . We will no longer place the components we want to render in any way v5 , but will uniformly pass it as the value of the element

no exact configuration

In v5 not added exact as Route assembly props words, if the URL begins with the keyword path, the path will match, because the matching process is top to bottom . But in v6, we will no longer need that exact configuration because the path pattern matching algorithm has changed and is now more enhanced.

In v5, we did this:

<Switch>
   {/* 三种Route组件使用定义 */}
   <Route path="/signup" component={Product} />
   {/* 或 */}
   {/* 这个方法允许我们将 props 传递给渲染的组件 */}
   <Route path="/games">
       <Product id={2} />
   </Route>
   {/* 或是通过render函数 */}
   <Route path="/games" render={(props) => <Product {...props} />} />
</Switch>

In v6,

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

Links and NavLinks

Link and NavLink components can still run in V6. Link component is used the same as it was in v5, but when using the NavLink component, the activeClassName and activeStyle . In v5, the activeClassName prop is used to automatically apply some CSS classes to the link activeStyle allows us to add internal styles to the link when it is activated.

But in v6, we can now use a function to get information about the link's active state. The argument to this function is an object with properties isActive . true when the link is active and 161e0f5531cdaf false inactive. isActive allows us to use conditional expressions to indicate the active style or class name.

In v5, we did this:

import {NavLink} from “react-router-dom”

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

But in v6 we will do this:

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

Navigate replaces Redirect

In v5 we use that Redirect component to bring one page to another, but it is no longer exported v6 in react-router-dom It has been replaced by the Navigate component.

In v5, we did this:

<Route path="/faq">
   <Redirect to="/about" />
</Route>
<Route path="/about" component={About} />

But in v6 we will do this:

<Route path="/games" element={<Navigate to="/about" />} />;
<Route path="/games" element={<About />} />;

It's important to note that if we just add the component the way Navigate does in the code snippet above, it will just push the navigation to that path onto the navigation stack, but if we're going to replace the current page with a new page, we'll replace the property Add to the Navigate component like this:
<Route path="/games" element={<Navigate replace to="/about" />} />;

Nested routes

As the name suggests, a nested route is a route that is placed inside another route. They are used to render more specific information in child components. In v6, we placed nested routes as child routes of parent routes. Then we introduce the Outlet component, which is react-router-dom in the render component, to specify where we want the nested information to appear. Outlet component is not required, but it makes the code cleaner.
In v5, we did this:

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>
   );
}

In v6 we do this:

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>
   );
}

Programmatic Navigation

occurs when the user is redirected due to an event that occurs on the path ( 161e0f5531cee9 such as button click, API request completion, etc. In v5, we can use the useHistory hook to do the following:

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>
   );
}

But in v6, the useHistory hook was replaced with the useNavigate hook, and we use it differently.

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>
   );
}

A cool thing is that we can go forward and back arbitrarily on the navigation stack. By using a positive number as the parameter navigate() above, the route will move forward by this number of steps. Negative numbers do the same thing backwards

// Goes forward
navigate(1)
// Goes forward twice
navigate(2)
// Goes backward
navigate(-1)
// Goes backward three times
navigate(-3)

Remove the Prompt component

The Prompt component in v5 prevents accidentally leaving the page if there are unsaved changes. But the react-router team did not include it in v6 , and there is no alternative. So if you need that functionality, you can implement it manually or go back to v5.

useBlocker nor usePrompt work except for not including Prompt in the current version (v6). react-router team although stated in the official documentation that they are currently working on adding it back to v6 , but not for the first stable release of 6.x.

generalize

Let's highlight the changes we've experienced.

  • The Switch component is replaced with the Routes component.
  • How to place changes to the Route's render component.
  • There is no exact in routing.
  • activeClassName and activeStyle no longer exist in NavLink components.
  • We can access the isActive state of the NavLink component through the function callback.
  • The Redirect component has been replaced with the Navigate component.
  • A more stylish way to implement nested routes.
  • No Prompt component

In conclusion, if you are not ready to switch from v5 or any other version to v6, you can continue to use it to install the previous version.

npm install react-router-dom@[VERSION_NUMBER]

However, you'll miss out on some goodies that come with v6, including but not limited to:

  • Enhanced path pattern matching algorithm.
  • According to Bundlephobia, the volume size has been reduced by 60%
  • I believe we were able to successfully switch to react-router v6 and stop using the Switch component (pun very intended) 😌.

    has a better coding experience 🙌.


前端晚间课
235 声望12 粉丝

引用和评论

0 条评论