react route guard (route interception)

Posted by abhic on Mon, 03 Jan 2022 22:44:11 +0100

Unlike Vue, react implements route interception by setting meta characters in the route. When using Vue, the framework provides the routing guard function to perform some verification before entering a certain road. If the verification fails, jump to 404 or login page, such as the beforeEnter function in Vue:

...
router.beforeEach(async(to, from, next) => {
    const toPath = to.path;
    const fromPath = from.path;
})
...

The basic idea of Route interception in react is to use the render function of Route. The jump of different components is realized by judging the interception conditions, so as to realize the interception. In previous versions, the React Router also provided a similar onEnter hook, but in the 4.0 version of React Router, this method was cancelled. After React Router 4.0, declarative components are used. Routing is a component. To realize the routing guard function, we have to write it ourselves.
If route guard is not used, the Router component looks like this:

import * as React from 'react';
import { HashRouter,Switch,Route,Redirect } from 'react-router-dom';
 
import Index from "./page/index";
import Home from "./page/home";
import ErrorPage from "./page/error";
import Login from "./page/login";
 
export const Router = () => (
    <HashRouter>
        <Switch>
            <Route path="/" exact component={Index}/>
            <Route path="/login" exact component={Login}/>
            <Route path="/home" exact component={Home}/>
            <Route path="/404" exact component={ErrorPage}/>
            <Redirect to="/404" />
        </Switch>
    </HashRouter>
);

The Router component above contains three pages:

land
homepage
404 page
And four routes:
Root routing
Login routing
Home page routing
404 routing
The root route and / home route are directed to the home route.
The above is a basic routing definition. You can jump back and forth between login / home page and 404 page, but there are also some problems:
In non login status, you can directly jump to the home page
In the login status, you can also enter the / login route to jump to the login page
Now, we want to complete this function:
In the non login state, you cannot jump to the home page directly. If you jump to the home page in the non login state, you need to redirect to the login route
In the login status, you cannot jump to the login page. If you jump to the login page in the login status, you need to redirect to the home page
To complete this function, there are two schemes:
In each component, jump according to the history object on props
Perform global routing guard processing

First, create a routermap under the following directory src JS file, the code is as follows:
Setting auth to true indicates that the route requires permission verification.

/**
 * Define the routing component and set auth to true, indicating that the route needs permission verification
 */

import Admin from "./pages/Admin";
import Login from "./pages/Login";
import Error from "./pages/Error";

export const routerMap = [
    {path: "/", name: "admin", component: Admin, auth: true},
    {path: "/login", name: "Login", component: Login},
    {path: "/error", name: "error", component: Error},
];

All route jumps are completed by FrontendAuth high-level component agent. Here is FrontendAuth JS component implementation:

/**
 * Routing guard verification
 */
import React, {Component} from "react";
import {Route, Redirect} from "react-router-dom";

class FrontendAuth extends Component {
    // eslint-disable-next-line no-useless-constructor
    constructor(props) {
        super(props);
    }

    render() {
        const {routerConfig, location} = this.props;
        const {pathname} = location;
        const isLogin = localStorage.getItem("user");
        console.log(pathname, isLogin);
        console.log(location);
        // If the route does not need permission verification, except the login page in login status
        // Because after logging in, you can't jump to the landing page
        // This part of the code is to access routes that do not require permission verification in the non login state
        const targetRouterConfig = routerConfig.find(
            (item) => item.path === pathname
        );
        console.log(targetRouterConfig);
        if (targetRouterConfig && !targetRouterConfig.auth && !isLogin) {
            const {component} = targetRouterConfig;
            return <Route exact path={pathname} component={component}/>;
        }
        if (isLogin) {
            // If you are in login status, you want to jump to login and redirect to the home page
            if (pathname === "/login") {
                return <Redirect to="/"/>;
            } else {
                // If the route is legal, jump to the corresponding route
                if (targetRouterConfig) {
                    return (
                        <Route path={pathname} component={targetRouterConfig.component}/>
                    );
                } else {
                    // If the route is illegal, redirect to 404 page
                    return <Redirect to="/error"/>;
                }
            }
        } else {
            // In the non login state, when the route is legal and permission verification is required, jump to the login page and require login
            if (targetRouterConfig && targetRouterConfig.auth) {
                return <Redirect to="/login"/>;
            } else {
                // In the non login state, if the route is illegal, redirect to 404
                return <Redirect to="/error"/>;
            }
        }
    }
}

export default FrontendAuth;

Then, define the Router component in app JS, the component is the result of high-level component packaging:

import './App.less';
import React, {Fragment} from "react";
import {Switch} from 'react-router-dom'
import FrontendAuth from "./FrontendAuth";
import {routerMap} from "./routerMap";

function App() {
    return (
        <Fragment>
            {/*If only one is matched, the matching will not go down if the matching is successful, which is efficient*/}
            <Switch>
                <FrontendAuth routerConfig={routerMap}/>
            </Switch>
        </Fragment>
    );
}

export default App;

test

Topics: Javascript React