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 🙌.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。