React: SPA Routing Configuration

Posted on 2020-12-23  1 View


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().