This topic describes how to use the react-router library to configure routes for single-page applications.
Objective
react-router is a routing library maintained by React, which is itself a React component. By switching different Route
objects to dynamically load the components on the page, the effect of switching pages is achieved. At the time of writing, react-router has been updated to version 5.2.0. Use the following command to install:
npm install --save react-router-dom
Basic usage
react-router provides a variety of Router objects: <BrowserRouter>
, <HashRouter>
, <StaticRouter>
, etc. We use the officially recommended <BrowserRouter>
as an example for this article. In actual implementation, one of the above five high-level routers is generally used, but the principle is not much different. The comparison between them will be described later.
Like other React components, <BrowserRouter>
needs to be introduced in js. Other components of the page need to be wrapped in it. For example:
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'
const App = () => {return <h1>Hello World!</h1>}
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
Link and Route objects
<Route>
object contains: the path
attribute, which is used to match URLs; The component
attribute, which specifies the element that needs to be rendered when the URL matches; The exact
attribute is used to specify whether the URL is strictly matched. Examples are as follows:
<BrowserRouter>
<Route exact path="/" component={App} />
<Route path="/index" component={Index}>
</BrowserRouter>
App components will
be loaded when the user accesses the root path, and IndexPage
will be loaded when the user accesses the /index
directory.
Note: If you do not add the exact
attribute to the following path route, the App
element will also be loaded when the /index
path is accessed.
Switch object
<Switch
in React > similar to switch usage in C, when it is used to switch to
the first matching routing branch, the other routing branches are not rendered. When multiple < Route >
objects are placed at the same level, we use <Switch >
element to wrap it. For example:
<BrowserRouter>
<Switch>
<Route exact path="/" component={App} />
<Route path="/index" component={Index}>
</Switch>
</BrowserRouter>
When using <Switch >
, if we do not specify the exact
attribute in the first route, then regardless of whether we access "/", "/index
", "/anything"
,`` The routers will match to the first route of the previous code without rendering other components.
Use history in the Router
To quote the official documentation: "React Router is built on history. In short, a history knows how to listen for changes in the browser's address bar, parse the URL into a location object, then use it to match to a
route, and finally render the corresponding component correctly. “
Since react-router v4, the official recommended <BrowserRouter >
has been configured internally, and we do not need to configure it additionally. For the underlying implementation of History, you can refer to this blog post: BrowserHistory Implementation Principles of React Routing
Navigate in other components
When we want to create hyperlinks in other components, we only need to use <Link>
or < NavLink >
object to complete the navigation. The latter is a special form of the former used to add style styles to links when they are selected. They end up being rendered as <a>
tags in HTML, just in a slightly different way. For example:
<Link to="/">Back To Home</Link>
<Link to={{
pathname: "/",
search: "/?id=0",
hash: "#hash location",
state: {jumpBack: true}}}>
Back To Home
</Link>
As shown in the above code, the to attribute accepts a string or location
type as a parameter. When the user clicks on the link, path, search, hash are merged into href. When the general process is reached, React will call the history.pushState
method to jump the URL and pass the state into the location object, and then trigger the
event listener in history to complete the update of the history
.
Nested routes
Suppose we have multiple subpages under the
/index path, such as /index/01, /index/02
, etc. `` We want to access these two pages via hyperlinks in the IndexPage, how do we configure subroutes in the IndexPage
component? Our existing index .js is as follows:
import...
function Index() {
return (
<div>
<ul>
<li> IndexPage01</li>
<li> IndexPage02</li>
</ul>
</div>
);
};
Creating a <Router >
in the current component and hardcodedURLs in the <Route >
is certainly a solution, but this will make it more difficult to debug and modify later. To avoid this approach, react-router, when creating rendered elements in the <Route >
element, passes a match
parameter to its props
, which refers to the path of the previous route. In this way, we can write the router of the current component more flexible, as follows:
import...
function Index(props) {
return (
<div>
<ul>
<li> <Link to={props.match.url}/01>IndexPage01</Link></li> <li> <Link to={props.match.url}/02>IndexPage02</Link></li>
</ul>
</div>
<BrowserRouter>
<Route path={props.match.url}/01 component={IndexPage01}/>
<Route path={props.match.url}/02 component={IndexPage02}/>
</BrowserRouter>
);
};
The
path and url parameters in match
can also be obtained by calling `let {path, url} = useRouteMatch().