Front-end routing is to display different routes corresponding to different content or pages. Routing can help us manage pages and codes well and enhance the user experience. The routing mode has two modes: hash and history, and the hash mode is usually used. In react, react-router is cross-platform, with built-in common components and common Hooks. react-router-dom provides Link and NavLink on the basis of react-router, and relies on the history library to provide two BrowserRouter and HashRouter applicable to browsers. Most current projects use react-router-dom. This article introduces the high frequency of use and the routing content I have come into contact with.
1. Routing principle
In layman's terms, routing is used to manage the relationship between url addresses and views. An address corresponds to the content to be displayed on a page. The address shown below is the hash mode (/#/)
principle:
1. Prepare the view (html)
2. Prepare the route for routing (it can be an object, the key name is the route name and the value is the view address)
3. Obtain the "view address" through the route of the hash address
4. In the specified label, load the required view page
Schematic : Soul Painter
Two, use
(1) Installation
npm i react-router-dom@5
(2) Import
import { ...generic component } from 'react-router-dom'
(3) use
<BrowserRouter >
<Route path="path" component={component}></Route>
</BrowserRouter >
3. General components
(1) BrowserRouter
In history mode, the principle of page jump is to use pushState and replaceState. Using this package, the form of the route will be displayed as /, which can be renamed by as. The general form is: BrowserRouter as Router (rename BrowserRouter to Router)
Attributes:
basename (string): The base url for all locations, the app is served from a subdirectory on the server, it needs to be set as a subdirectory, a well-formed basename should start with a slash but not end with a slash
getUserConfirmation(fn): The function used to confirm the navigation, the default is to use window.confirm
<BrowserRouter>
<Route path='/films' component={Films}></Route>
<Route path='/home' component={Home}></Route>
</BrowserRouter>
(2) HashRouter
In hash mode, the principle of page jump is to use location.hash and location.replace. Using this package, the form of routing will be displayed as /#/, although it is long and ugly, it is used more
<HashRouter>
<Route path='/films' component={Films}></Route>
<Route path='/home' component={Home}></Route>
</HashRouter>
Note: The difference between BrowserRouter and HashRouter
1. The underlying principles are different
HashRouter uses the hash value of Url
BrowserRouter uses the history api of h5, which is not compatible with ie9 and below
2. The expression form of path is different. HashRouter has a # sign
3. HashRouter refreshes the influence on routing state parameters, while BrowserRouter saves the state in the history object
4. HashRouter can be used to solve some path error related problems
(3) Route
Matches the component, and displays the component. That is, after the matching is successful, the component is immediately replaced with the matching component
Attributes | type | effect |
path | str | obj | A route matches a path, a Route without a path attribute will always match |
exact | bool | When true, full path matching (/home) is required. The route defaults to "contain" (/ and /home) to match, which means that multiple Routes can be matched and rendered at the same time |
component | fn | component | React components will only be rendered when the address matches, and route props will also be rendered together |
render | func | Rendering and wrapping components inline requires the use of the target component to be returned |
<Route path='/films' component={Films} />
or
<Route path="/" exact render={() => {
return <IndexPage user={user} />
}} />
Note: fuzzy match and exact match
Because of the existence of exact, it is divided into fuzzy matching and exact matching
(4) Switch
Exclusive (single) match. If you don’t want to use inclusiveness, then use Switch, which is similar to the switch branch statement in js. The wrapped components will be matched to one and jump out to the end. It is often used in sidebars and boot tabs
Attributes | type | effect |
location | str | obj | Generally we don't set the location property for this component. Not set: The subcomponents of the Switch component (usually Route or Redirect) will perform route matching based on the location of the current browser as the matching basis. |
<HashRouter>
{/*Switch is similar to the Switch branch in Js, it is wrapped like a case, it can always match one, and jump out*/}
{/* In this way, one page can be displayed, and multiple pages will not be displayed on one page*/}
<Switch>
<Route path='/films' component={Films}></Route>
<Route path='/home' component={Home}></Route>
</Switch>
</HashRouter>
(5) Redirect
Redirection, if the user enters /, when seeing /, it will specify to jump to the redefined page. Exact is used here, and the function is precisely matched. Only when it sees only / will it be redirected. Fuzzy matching, as long as it contains / will respond
Attributes | type | effect |
from | string | from |
to | string object | whereabouts |
push | boolean | add history |
exact | boolean | strict match |
sensitive | boolean | case sensitive |
<HashRouter>
<Route path='/films' component={Films}></Route>
<Route path='/home' component={Home}></Route>
{/* fuzzy match*/}
{/* <Redirect from='/' to='/home'/> */}
{/* exact match*/}
<Redirect from='/' to='/home' exact/>
</HashRouter>
Reminder : If there is no sub-route, it is recommended that you add one exact
; if there is a sub-route, it is recommended to add it in the sub- exact
router, but not in the parent route; strict
but for whether there is a backslash, generally you can ignore it and not configure it
(6) Link
Equivalent to a tag, after react renders the virtual DOM into a real DOM, the Link component is also rendered into a tag, which is often used for navigation
Attributes | type | effect |
to | str | obj{pathname:,search:,hash:} | The path or address to jump to |
replace | bool | Whether to replace history |
<ul>
<li>
<Link to='/films'>电影</NavLink>
</li>
<li>
<Link to='/cimans'>Cinema</NavLink>
</li>
<li>
<Link to='/home'>我的</NavLink>
</li>
</ul>
(7) NavLink
The NavLink method is equivalent to the enhanced version of Link
Attributes | type | effect |
to | str | obj{pathname:,search:,hash:} | The path or address to jump to |
replace | bool | Whether to replace history |
activeClassName | str | Set the selected style, the default value is active |
activeStyle | obj | Add style to this element when the element is selected |
exact | bool | When true, the class and style will only be applied if the resulting and exact match |
strict | bool | When true, a slash after a location pathname will be considered when determining whether a location matches the current URL |
isActive | fun | The function of extra logic to determine whether the link is activated |
<ul>
<li>
<NavLink to='/films'>电影</NavLink>
</li>
<li>
<NavLink to='/cimans'>影院</NavLink>
</li>
<li>
<NavLink to='/home'>我的</NavLink>
</li>
</ul>
(8) withRouter
Wrap a component inside Route
, and then react-router
the three objects history, location, match
will be put props
into the properties of this component.
// withRouter实现原理:
// 将组件包裹进 Route, 然后返回
// const withRouter = () => {
// return () => {
// return <Route component={Nav} />
// }
// }
// 这里是简化版
const withRouter = ( Component ) => () => <Route component={ Component }/>
//withRouter的返回值是一个新组件
If we have something that is not one Router
, but we need to rely on it to go forward and back through browsing records, then we can use it withRouter
to turn general components into routing components. Usage scenario : For example, click on the logo of the page to return to the home page. At this time, you can use withRouter to do it
import React, { Component } from 'react'
import {withRouter} from 'react-router-dom' //引入withRouter
class Header extends Component {
back = ()=>{
this.props.history.goBack()
}
forward = ()=>{
this.props.history.goForward()
}
go = ()=>{
this.props.history.go(-2)
}
render() {
console.log('Header组件收到的props是',this.props);
return (
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={this.back}>回退</button>
<button onClick={this.forward}>前进</button>
<button onClick={this.go}>go</button>
</div>
)
}
}
export default withRouter(Header)
//withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
//withRouter的返回值是一个新组件
3. General Hooks
It is used in version 5.1 and later, and it can only be used in functional components. For usage, see the code demonstration when passing parameters in the fourth point
(1) useHistory
Get the History object. Access the history object for programmatic navigation
//import
import {useHistory } from "react-router-dom"
const Home = () => {
return (
<div>Home</div>
)
}
const Detail = () => {//use
const history = useHistory()
console.log("history", history);//Get the History object
console.log("Get the current page path", history.location.pathname);//Get the current page path
//Consistent with the following obtained through js
console.log(props.location.pathname);
return (
<div><-- 使用-->
<button onClick={() => { history.push('/')}}>go home</button>
</div>
)
}
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/detail/:id" component={Detail}/>
</Switch>
</Router>
</div>
);
}
(2) useLocation
Get the Location object. In each layer of components, it is easy to obtain the location object. Before V5.1, we need to use props.location. For deeper components, you also need to usewithRouter
//import
import {
useLocation
} from "react-router-dom";
//use
const location = useLocation ()
console.log("location",location);
(3) useParams
Get the object of the key-value pair of the route parameter, and access the match.params of the current <Route>. Before V5.1, we need to props.match
obtain route parameters. For deeper components, you also need to use higher-order componentswithRouter
//设置<Route>的match.params
<Router>
<Switch>
<Route path="/:path">
<Home></Home>
</Route>
</Switch>
</Router>//Obtain
let { path } = useParams();
console.log("path ",path );
(4) useRouteMatch
useRouteMatch
, accepting a path
string as a parameter. When the parameter path
matches the current route, useRouteMatch will return the match object, otherwise it will return null.
useRouteMatch
For some, not route-level components. However, it is very useful when the component itself is visible and hidden but is related to the current path.
For example, when you are working on a background management system, the header of the web page will only be displayed on the login page, and it does not need to be displayed after the login is completed. It can be used in this scenario useRouteMatch
.
const Home = () => { return ( <div>Home</div> ) } // Header component will only appear when matching `/detail/:id` const Header = () => { // Only the current path When matching `/detail/:id`, match is not null const match = useRouteMatch('/detail/:id') return ( match && <div>Header</div> ) } const Detail = () => { return ( <div>Detail</div> ) } function App() { return ( <div className="App"> <Router> <Header/> <Switch> <Route exact path="/"component={Home}/>
<Route exact path="/detail/:id" component={Detail}/>
</Switch>
</Router>
</div>
);
}
(5) useRoutes
Routing table, the hook is useRoutes
functionally equivalent to <Routes> , but inside it uses JavaScript 对象
instead of <Route>
elements to define your routes
-
useRoutes()
The parameter is an array. -
useRoutes
The return value of is either a valid React element that can be used to render the route tree, ornull
an element that doesn't match. -
Nested routes are implemented with children.
Use useRoutes to achieve:
import * as React from "react";
import { useRoutes } from "react-router-dom";function App() {
let element = useRoutes([
{
path: "/",
element: <Dashboard />,
children: [
{
path: "messages",
element: <DashboardMessages />,
},
{ path: "tasks", element: <DashboardTasks /> },
],
},
{ path: "team", element: <AboutPage /> },
]);return element;
}
Use Routes and Route to achieve:
<Routes>
<Route path="/" element={<Dashboard />}>
<Route
path="messages"
element={<DashboardMessages />}
/>
<Route path="tasks" element={<DashboardTasks />} />
</Route>
<Route path="about" element={<AboutPage />} />
</Routes>
4. Routing parameters
In v5.x, there is only a programmatic way to obtain parameters. After adding Hooks in v5.1 and later, you can use the programmatic method to obtain the parameters carried by the url, or use the method in Hooks to obtain (only Functional components), the former one also becomes explicit parameter passing, and the latter two become implicit parameter passing
(1) params parameters
1. Register routing
// register route
<Route path="/details/:name/:age" component={Details}/>
2. Routing jump
//routing jump
<Link to='/details/tom/18'}>详情</Link>
or
<button onClick={()=>{props.history.push('details/tom/18')}}>Go to the details page</button>
3. Obtain parameters on the details page
//Get parameters on the details page
console.log(props.match.params);
or
import { useParams } from "react-router-dom";
const params = useParams();
(2) search parameter
1. Register routing
// register route
<Route path="/details" component={Details}/>
2. Routing jump
//routing jump
<Link to='/details/tom/18'}>详情</Link>
or
<button onClick={()=>{props.history.push('details?name=tom&age=18')}}>Go to the details page</button>
3. Obtain parameters on the details page
//Get parameters on the details page
console.log(props.location.search);//Get ?id=1&age=18,
or
import { useParams } from "react-router-dom";
const params = useParams(); get ?id=1&age=18
In the above two methods, the obtained search is a urlencoded encoded string, and it is necessary to parse the parameters into an object with the help of query-string or encapsulate an intercepted tool function by yourself
const { search } = props.location
const { num } = qs.parse(search.slice(1))
(3) state parameters
1. Register routing
// register route
<Route path="/details" component={Details}/>
2. Routing jump
//routing jump
<Link to={ {
pathname:'/detils',
state:{
id:1,
age:18
}
}} > Go to the details page </Link>
or
<button onClick={()=>{props.history.push({
pathname:'/details',
state:{
id:1,
age:18
}
})}}>Go to the details page</button>
3. Obtain parameters on the details page
//Get parameters on the details page
console.log(props.history.location.state);//{id: 1, age: 18}
import { useLocation } from "react-router-dom";
const { state } = useLocation();
console.log(state);//{id: 1, age: 18}