Route management and route interception scheme of react router V6

Posted by phphead on Fri, 07 Jan 2022 05:12:33 +0100

The last one was shared Route management and interception scheme of react router V5 However, there are some defects, such as not supporting nested routing, not supporting dynamic routing parameters and so on.

Later, I saw the characteristics of useRoutes api in react router v6 version, decided to upgrade to v6 version, and reconstructed the implementation scheme of route management and route interception.

At present, there are few articles on the Internet in v6 version, and the implementation process basically depends on your own exploration. The specific scheme is shared below.

1, React router V6

  • Official documents: https://github.com/remix-run/react-router/blob/main/docs/api.md
  • At present, the official documents are only in English. There are Chinese tutorials on the Internet.
  • Here we only mention a new api: useRoutes.
    useRoutes can read a routing configuration array and generate the corresponding routing component list. Similar to the function of the previous react router config plug-in, it is much easier to use this api for the implementation of unified routing management.

2, Unified routing management

1. Routing profile

Item Src / router / index JS to fill in the routing configuration:

import Index from '@/views/index/index'
import Login from '@/views/login/index'
import Page404 from '@/views/test/page404'

const routes = [
  {
    path: '/index',
    element: <Index />,
  },
  {
    path: '/login',
    element: <Login />,
  },
  {
    path: '*',
    element: <Page404 />,
  },
]

export default routes

2. Introducing routing configuration

(1) Project entry file Src / index Introducing router component into JS:

import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { BrowserRouter } from 'react-router-dom'

ReactDOM.render(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>,
  document.getElementById('root')
)
  • The routing browser / history mode uses BrowserRouter, and the hash mode uses HashRouter.
  • If the project is deployed under the server domain name subdirectory, configure the basename attribute for BrowserRouter.

(2) Project entry component Src / APP Introducing routes configuration into JSX:

import { useRoutes } from 'react-router-dom'
import routes from '@/router'

function App () {
  const elements = useRoutes(routes)
  return elements
}

export default App
  • useRoutes can only be used in the router context, so useRoutes need to be written in a sub component and referenced by BrowserRouter.

3, Global route interception

Realize the global interception of routing, and define some judgment processing.
The implementation idea here is to control the element attribute of routing configuration.

1. Wrapper functionfn

Create a new file Src / components / routerguard / FN js:

import { Suspense, lazy } from 'react'
import { Navigate } from 'react-router-dom'
import Guard from './guard'

// Route lazy loading
export function lazyLoad (importFn, meta) {
  const Element = lazy(importFn)
  const lazyElement = (
    <Suspense fallback={<div></div>}>
      <Element _meta={meta}/>
    </Suspense>
  )
  return <Guard element={lazyElement} meta={meta} />
}

// Route general load
export function load (element, meta) {
  return <Guard element={element} meta={meta} />
}

// Set route navigation guard function
let handleRouteBefore = null
export function setRouteBefore (fn) {
  handleRouteBefore = fn
}
export function getRouteBefore () {
  return handleRouteBefore
}

// Route redirection
export function redirect (path) {
  return <Navigate to={path} />
}
  • The load function here is used as an alternative. In general, the lazload function is recommended.
  • The fallback value in the lazload function is the loading component during route switching, which can be encapsulated and referenced by itself.

2. Package routing container component guard

New component Src / components / routerguard / guard jsx:

import { Navigate, useLocation } from 'react-router-dom'
import { getRouteBefore } from './fn'

let temp = null // Used to prevent duplicate rendering

function Guard ({ element, meta }) {
  const location = useLocation()
  const { pathname } = location
  meta = meta || {}

  const handleRouteBefore = getRouteBefore()
  if (handleRouteBefore) {
    if (temp === element) {
      return element
    }
    const newPath = handleRouteBefore({ pathname, meta })
    if (newPath && newPath !== pathname) {
      element = <Navigate to={newPath} />
    }
  }

  temp = element
  return element
}

export default Guard
  • In strict mode, the component will be rendered twice, so it is processed with temp here.

3. Reference encapsulated RouterGuard

Project routing configuration file Src / router / index JS reference:

import { lazyLoad, redirect, setRouteBefore } from '@/components/RouterGuard/fn'

// Global routing configuration
const routes = [
  {
    path: '/',
    element: redirect('/index'),
  },
  {
    path: '/index',
    element: lazyLoad(() => import(/* webpackChunkName: "index" */ '@/views/index/index'), {
      title: 'home page',
      needLogin: true,
    }),
  },
  {
    path: '/login',
    element: lazyLoad(() => import(/* webpackChunkName: "login" */ '@/views/login/index'), {
      title: 'Sign in',
    }),
  },
  {
    path: '*',
    element: lazyLoad(() => import(/* webpackChunkName: "404" */ '@/views/test/page404'), {
      title: '404',
    }),
  },
]

/**
 * @description: Global route interception
 * @param {string} pathname Current routing path
 * @param {object} meta Current route custom data
 * @return {string} Return the path of the page when you need to jump to another page
 */
const onRouteBefore = ({ pathname, meta }) => {
  // Dynamically modify page title
  if (meta.title !== undefined) {
    document.title = meta.title
  }
  // Judge not logged in jump to login page
  if (meta.needLogin) {
    if (!isLogin) {
      return '/login'
    }
  }
}
setRouteBefore(onRouteBefore)

export default routes
  • Here, the second field of each lazload function is the custom meta data, which will also be displayed in_ The meta field name is passed as an attribute to each routing component as an alternative.

be accomplished.

4, Summary

Implementation functions:
+ Unified management of global routes, supporting convenient configuration of route redirection, lazy loading and customization meta Fields, etc.
+ Global route interception supports reading routes meta Configuration, support interception and jump to other routes, etc.
+ It also supports nested routing, dynamic routing parameters and other official routing configuration methods.

Topics: Javascript Front-end React react-router