Introduction to the
The React Router library contains three different NPM packages, each of which has a different purpose.
- React-router: A core library that contains most of the core functions of the React Router, including the routing matching algorithm and most of the core components and hooks.
- React-router-dom: A routing package for the React application that includes everything about the React-Router and adds DOM-specific apis, including BrowserRouter, HashRouter, and Link.
- React-router-native: Used to develop react Native applications, including all the contents of the React-Router, and adding some React Native specific apis, including NativeRouter and Link.
version
The following V5 is listed from all versions of 5.1.2. There are many alpha and beta minor versions of V6 not listed.
The new project currently uses 6.0.2, while the old project used 5.1.2.
react-router-dom NPM address
version | downloads | Release Date (comparison date 2022.1.14) |
---|---|---|
6.2.1 | 818595 | A month ago |
6.0.2 | 464961 | 2 months ago |
6.0.0 | 5540 | 2 months ago |
5.3.0 | 1612985 | Four months ago |
5.2.1 | 68038 | Five months ago |
6.0.0 – beta. 0 | 62966 | Two years ago |
5.2.0 | 1734184 | Two years ago |
6.0.0 – alpha. 0 | 7 | Two years ago |
5.1.2 | 462691 | Two years ago |
Compared to V5, the packaged package size is reduced from 20.8K to 10.8K. Package analysis website
The installation
/ / NPM installation
npm install react-router-dom@6
/ / yarn installation
yarn add react-router-dom@6
Copy the code
Enable the global routing mode
Two common routing modes are available for global routing: HashRouter and BrowserRouter are hash and History modes, respectively.
USES BrowserRouter:
import * as React from "react";
import * as ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>.document.getElementById("root"));Copy the code
App.jsx Sets the route
import './App.css';
import { Routes, Route, Link } from "react-router-dom"
function App() {
return (
<div className="App">
<header className="App-header">
<Routes>
<Route path="/" element={<Home />} ></Route>
<Route path="/about" element={<About />} ></Route>
</Routes>
</header>
</div>
);
}
function Home() {
return <div>
<main>
<h2>Welcome to the homepage</h2>
</main>
<nav>
<Link to="/about">about</Link>
</nav>
</div>
}
function About() {
return <div>
<main>
<h2>Welcome to the about page</h2>
</main>
<nav>
<ol>
<Link to="/">home</Link>
<Link to="/about">about</Link>
</ol>
</nav>
</div>
}
export default App;
Copy the code
Writing in the front
If you’re just starting out with React Router, or if you want to try v6 with a new application, seeGetting started guide.
The following describes the new features compared to React Router V5 and how to make a quick migration.
Preparing for the Upgrade
1. Upgrade to React V16.8
React Router V6 makes extensive use of React hooks, so you need to use React 16.8 or later before attempting to upgrade to React Router V6. The good news is that React Router V5 is compatible with React >= 15, so if you’re using V5 (or V4), you should be able to upgrade React without touching any Router code.
2. Upgrade to React Router V5.1 (optional)
Switching to React Router V6 will be easier if you upgrade to V5.1 first. Because in V5.1, enhancements to element handling were released, this will help smooth the transition to V6. Instead of using props, use regular elements everywhere and use hooks to access the internal state of the router.
Upgrade to React Router v6
- Let me rename it to.
- New feature changes.
- Nested routines have been made easier.
- Use enavigate instead of useHistory.
- The new hook useRoutes replaces react-router-config.
1. <Switch>
rename<Routes>
React Router V6 introduces a Routes component that is similar to the previous Switch but more powerful. It includes functions such as relative routing and linking, automatic routing ranking, nested routing and layout.
// v5
<Switch>
<Route exact path="/"><Home /></Route>
<Route path="/profile"><Profile /></Route>
</Switch>
// v6
<Routes>
<Route path="/" element={<Home />} / ><Route path="profile/*" element={<Profile />} / ></Routes>
Copy the code
2. <Route>
New feature changes
Route is responsible for rendering the React component’s UI. Two attributes are used in V6:
- Path: matches the URL of the current page.
- Element: This is added to determine which component to render when routing matches. In V5, we usually used the component property, or render.
Simply put, Component /render is replaced by element
// v5
<Route path=":userId" component={Profile} />
<Route
path=":userId"
render={routeProps= > (
<Profile routeProps={routeProps} animate={true} />)} / >
// v6
<Route path=":userId" element={<Profile />} / >
<Route path=":userId" element={<Profile animate={true} />} / >
Copy the code
3. Nesting routines are simpler
Nesting is common in practical applications, such as the following two pages. The User component is shared, and when switching routes, only the Profile and Posts subcomponents are changed.
In React Router V5, nested routines must be clearly defined. React Router V6 does not. It picks the best element from the React Router library called Outlet to render any matching child elements for a particular route. It works just like the Vue Router.
3.1 Outlet realizes nested routines by
- Nested routines are implemented in V5 by
// v5
import {
BrowserRouter,
Switch,
Route,
Link,
useRouteMatch
} from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/profile" component={Profile} />
</Switch>
</BrowserRouter>
);
}
function Profile() {
let { path, url } = useRouteMatch();
return (
<div>
<nav>
<Link to={` ${url} /me`} >My Profile</Link>
</nav>
<Switch>
<Route path={` ${path} /me`} >
<MyProfile />
</Route>
<Route path={` ${path} /:id`} >
<OthersProfile />
</Route>
</Switch>
</div>
);
}
Copy the code
- V6 implementation of nested routines by, you can delete string matching logic. You don’t need any useRouteMatch(). Take advantage of the new API: Outlet (further simplified by taking advantage of useRoutes, discussed in point 5 below).
import { Outlet } from 'react-router-dom';
Copy the code
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} / ><Route path="profile" element={<Profile />} ><Route path=":id" element={<MyProfile />} / ><Route path="me" element={<OthersProfile />} / ></Route>
</Routes>
</BrowserRouter>
);
}
function Profile() {
return (
<div>
<nav>
<Link to="me">My Profile</Link>
</nav>{/* Will render directly based on the different routing parameters defined above<MyProfile />or<OthersProfile />* /}<Outlet />
</div>)}Copy the code
More than 3.2<Routes />
Previously, we could only use one Routes in the React App. But now we can use multiple routes in the React App, which will help us manage multiple application logic based on different routes.
import React from 'react';
import { Routes, Route } from 'react-router-dom';
function Dashboard() {
return (
<div>
<p>Look, more routes!</p>
<Routes>
<Route path="/" element={<DashboardGraphs />} / ><Route path="invoices" element={<InvoiceList />} / ></Routes>
</div>
);
}
function App() {
return (
<Routes>
<Route path="/" element={<Home />} / ><Route path="dashboard/*" element={<Dashboard />} / ></Routes>
);
}
Copy the code
4. Use enavigate instead of useHistory
From being clear to being blind…
// v5
import { useHistory } from 'react-router-dom';
function MyButton() {
let history = useHistory();
function handleClick() {
history.push('/home');
};
return <button onClick={handleClick}>Submit</button>;
};
Copy the code
Now history.push() will be replaced with navigation()
// v6
import { useNavigate } from 'react-router-dom';
function MyButton() {
let navigate = useNavigate();
function handleClick() {
navigate('/home');
};
return <button onClick={handleClick}>Submit</button>;
};
Copy the code
The use of history will also be replaced with:
// v5
history.push('/home');
history.replace('/home');
// v6
navigate('/home');
navigate('/home', {replace: true});
Copy the code
5. Replace react-router-config with the new hook useRoutes
This is done with hooks, which are much cleaner than writing the router component directly to the JSX file above
function App() {
let element = useRoutes([
{ path: '/'.element: <Home /> },
{ path: 'dashboard'.element: <Dashboard /> },
{ path: 'invoices'.element: <Invoices />,
children: [
{ path: ':id'.element: <Invoice /> },
{ path: 'sent'.element: <SentInvoices />}},// 404 not found
{ path: The '*'.element: <NotFound />}]);return element;
}
Copy the code
The project practice
The following examples are based on useRoutes
In this example, the fullPath attribute is a self-defined unofficial attribute, because when nested routines are created, only relative paths need to be written. The React Router does not use this property to see the full path containing the parent path.
1. The lazy loading
import { useRoutes } from 'react-router-dom'
/ / lazy loading
const lazyLoad = (path: string) = > {
const Comp = React.lazy(() = > import(`@page/${path}`))
return (
<React.Suspense fallback={<>Loading in...</>} ><Comp />
</React.Suspense>
)
}
const routers = [
{
name: 'the project'.path: '/'.element: <Backbone />,
children: [
{
name: 'home'.path: 'index/*'.// This attribute is not used in actual route rendering.
fullPath: '/index'.element: lazyLoad('IndexPage')}]]const Index = () = > useRoutes(routers)
export default Index
Copy the code
2. Index Route: indicates the default sub-route
Set the rendering component for nested routines that match only parent paths. When nested routines have multiple child routes but cannot determine which child route to render by default, you can add index attribute to specify the default route.
The index route differs from other routes in that it has no path attribute and shares the same path with the parent route.
For example, the following route sets up two invoices, namely /foo/invoices and /foo/activity. But when the page accesses /foo directly, the page doesn’t know how to render. In this case, you can set the default display to the invoices through index.
const routers = [
{
name: 'the project'.path: '/foo'.element: <Layout />,
children: [
// If only the parent route is matched, set index to true and do not specify path
{ index: true.element: lazyLoad('Invoices')}, {name: 'home'.path: 'invoices'.element: lazyLoad('Invoices')}, {name: 'about'.path: 'activity'.element: lazyLoad('Activity'}]}]Copy the code
3. 404
Deprecated Redirect in V5
// V5 is deprecated
const routers = [
{ path: 'home'.redirectTo: '/'}]// 404 can be written like this
const routers = [
{
name: '404'.path: The '*'.element: <NoMatch />}]Copy the code
4. Dynamic routes
We often need to map all the routes that a pattern matches to the same component. For example, the News details page, corresponding to different News, corresponding to the News component, the path may be News /1, News /2… . The number 1 indicates the ID of the news. This is a dynamic change.
- Dynamic path parameters start with a colon
const routers = [
{
name: 'Notice Details Page'.// Dynamic path parameters start with a colon
path: 'noticeDetail/:id'.fullPath: '/noticeDetail'.element: lazyLoad('NoticeDetail')}, {name: 'Help Centre Details Page'.path: 'helpCenterDetail/:fid/:sid'.fullPath: '/helpCenterDetail'.element: lazyLoad('HelpCenterDetail')}]Copy the code
-
UseParams Is used by components to obtain dynamic path parameters
For example, in the example above, there are two dynamic parameters fid and SID in the HelpCenterDetail component:
import { useParams } from 'react-router-dom'
const { fid, sid } = useParams()
Copy the code
5. Route wildcard
The following wildcard numbers are supported. Note: * is used only after /, not in the middle of the actual path
/groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*
Copy the code
The following are not supported in V6
/users/:id?
/tweets/:id(\d+)
/files/*/cat.jpg
/files-*
Copy the code
6. Url search parameters
Use of useSearchParams.
For example: http://URL/user? Id =111, obtain the value of id
import { useSearchParams } from 'react-router-dom'
const [searchParams, setSearchParams] = useSearchParams()
// Get parameters
searchParams.get('id')
// Check whether the parameter exists
searchParams.has('id')
// You can also use the set method to change the route within the page
setSearchParams({"id":2})
Copy the code
7. withRouter
V6 no longer provides withRouter, slightly cratered.
Official explanation: This problem usually arises when you use a React class component that does not support hooks. In React Router V6, we fully accepted the hooks and used them to share the internal state of all routers. But that doesn’t mean you can’t use a router. Assuming you can actually use hooks (you’re using React 16.8+), you just need a wrapper.
import {
useLocation,
useNavigate,
useParams
} from "react-router-dom";
function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{. props}
router={{ location.navigate.params}} / >
);
}
return ComponentWithRouterProp;
}
Copy the code
Complete examples in the project
import { useRoutes } from 'react-router-dom'
import Backbone from '.. /layouts/Backbone'
import InfoPage from '.. /pages/InfoPage/index'
import DataCenterPage from '.. /pages/DataCenterPage/index'
import NoMatch from './NoMatch'
/ / lazy loading
const lazyLoad = (path: string) = > {
const Comp = React.lazy(() = > import(`@page/${path}`))
return (
<React.Suspense fallback={<>Loading in...</>} ><Comp />
</React.Suspense>
)
}
const routers = [
{
name: 'the project'.path: '/'.element: <Backbone />,
children: [
// Matches only the parent route
{ index: true.fullPath: '/'.element: lazyLoad('IndexPage')}, {name: 'home'.path: 'index/*'.fullPath: '/index'.element: lazyLoad('IndexPage')}, {name: 'Message center'.path: 'info/'.// element: lazyLoad('InfoPage'),
element: <InfoPage />,
children: [
{ index: true.fullPath: '/info'.element: lazyLoad('NoticeList')}, {name: 'notice'.path: 'noticeList'.fullPath: '/info/noticeList'.element: lazyLoad('NoticeList')}, {name: 'Help Center'.path: 'helpCenter'.fullPath: '/info/helpCenter'.element: lazyLoad('HelpCenter'}]}, {name: 'I want to promote it.'.path: 'activityList/*'.fullPath: '/activityList'.element: lazyLoad('ActivityList')}, {name: 'Data center'.path: 'data/'.// element: lazyLoad('InfoPage'),
element: <DataCenterPage />,
children: [
{ index: true.fullPath: '/data'.element: lazyLoad('Order')}, {name: 'Order Query'.path: 'order'.fullPath: '/data/order'.element: lazyLoad('Order')}, {name: 'Revenue Query'.path: 'reward'.fullPath: '/data/reward'.element: lazyLoad('Reward')}, {name: 'Settlement Enquiry'.path: 'settlement'.fullPath: '/data/settlement'.element: lazyLoad('Settlement'}]}]}, {name: 'Notice Details Page'.// Dynamic routing
path: 'noticeDetail/:id'.fullPath: '/noticeDetail'.element: lazyLoad('NoticeDetail')}, {name: 'Help Centre Details Page'.path: 'helpCenterDetail/:fid/:sid'.fullPath: '/helpCenterDetail'.element: lazyLoad('HelpCenterDetail')}, {name: 'Personal Registration Page'.path: 'register/person'.fullPath: '/register/person'.element: lazyLoad('PersonBaseInfo')}, {name: '404'.path: The '*'.element: <NoMatch />}]const Index = () = > useRoutes(routers)
export default Index
Copy the code
Common routing components and hooks
Complete API: reactrouter.com/docs/en/v6/…
Component name | role | instructions |
---|---|---|
<Routers> |
A set of routing | Instead of the original<Switch> , all child routes are represented by the basic Router children |
<Router> |
Based on the routing | The Router can be nested, addressing the rigid pattern of the original V5 |
<Link> |
Navigation components | Skip to the actual page |
<Outlet/> |
Adaptive rendering components | The component is automatically selected based on the actual ROUTE URL, which is mainly used for nested routes, similar to Vue Router<router-view> |
Hooks, | role | instructions |
---|---|---|
useParams | Return current parameter | Read parameters based on the path |
useNavigate | Return current route | Replace useHistory in V5 |
useOutlet | Returns the element generated based on the route | |
useLocation | Returns the current Location object | |
useRoutes | The same as the Routers, but only used in JS | Instead of react — the router config |
useSearchParams | Matches? In the URL. Search parameters that follow |
reference
React Router address: React Router
The React the Router documentation: reactrouter.com/docs/en/v6
Complete API: reactrouter.com/docs/en/v6/…
react-router-dom: NPM address
Reference blog: blog.csdn.net/weixin_4090…
zhuanlan.zhihu.com/p/191419879
www.jianshu.com/p/03234215a…
Blog.csdn.net/zjjcchina/a…
Package size analysis at bundlephobia.com/