{react-router-dom v6} {react-router-dom v6} {react-router-dom v6} ‘Switch’ is not exported from ‘react-router-dom’….

React-router-dom V6 is not compatible with the react-router-config API. React-router-dom v6 is not compatible with the react-router-config API. React-router-dom v6 is compatible with the react-router-config API.

A quick overview of what has changed in v6

First, v6 changes

0,<Route>Path change

  • Placeholders * and :id are available, but re is not
  • All path matching in V6 will ignore the tail on the URL.”/
// v6
/user/*
/detail/:id
Copy the code

1.<Switch>rename<Routes>

It’s just a different name

<Switch> <Route path="/index1">< index1 /></Route> <Route path="/index2">< /Route> </Switch> <Route path="/index1"><Index1/></Route> <Route path="/index2"><Index1/></Route> </Routes>Copy the code

2,<Route>Component becomes Element

Component ={index1} element={< index1 />} element={< index1 />} />Copy the code

3,<Outlet>Render child routes

RenderRoutes like props. Children and react-router-config, or

for vue.

<BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="/content" element={<Content />}> <Route path="index1" element={<Index1 />} /> <Route path="index2" element={<Index2 />} /> </Route> </Routes> </BrowserRouter> // Content import {Outlet} from 'react-router-dom' function Content() {return (<div> <title> this is Content</title> {/* Render sub-routing here!! */} <Outlet /> {/* Here render child routing!! end */} </div> ) }Copy the code

4. useHistoryNo, use ituseNavigateInstead, page jumps are written differently

Import {useHistory} from 'react-router-dom'; . const history = useHistory() history.push('/index1') history.replace('/index2') ... // v6 import { useNavigate } from 'react-router-dom'; . const navigate = useNavigate(); navigate('/index1') navigate('/index2', {replace: true}) ...Copy the code

5,<Redirect/>Gone, new<Navigate/>alternative

Usage feels the same…

<Redirect to='index1' />
<Navigate to='index1' />
Copy the code

The highlight came, newuseRoutesCan be used instead of react-router-config

Render the route with useRoutes and pass in routes that we have centrally configured

const routes = { path: '/', element: <SecurityLayout />, children: [ { path: '', element: <Navigate to="/user/login" />}, // Redirect! {path: ", Element: <BasicLayout />, children: // BasicLayout Business page {path: 'index1', element: < index1 />}, {path: 'index2', element: <Index2/> }, ] }, ] } function RenderRoutes() { const element = useRoutes(routes) return element; }Copy the code

React-router V6 should have many other changes, but these are the ones that are currently involved in the code changes, so this article only introduces them

Use useRoutes to implement react-router-config

Once we understood the differences, we made changes at the code level

1. Modify routes

  • The parent routes are matched with asterisks (*)
  • Child routes do not need to carry the path of the parent route. For example, write ‘login’ instead of ‘user/login’.
  • Component to element
  • Child route key changed from ‘routes’ to ‘children’
  • If there is a redirection, useelement: <Navigate />
import Login from '@/pages/login'

const routes = [
  // UserLayout
  {
    path: 'user/*',
    element: <UserLayout />,
    children: [
      { path: '', element: <Navigate to="login" /> }, // Redirect
      {
        path: 'login',
        element: <Login />
      },
      route404
    ]
  },
]
Copy the code

2. In app.jsx,useRoutesPut it outside the Function App

Actually, useRoutes, to be exactWhere theThe component to be in<Router>The interior of the

After seeing the introduction of useRoutes, I started by writing:

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

function App() {
  const element = useRoutes(routes)
  return (
    <HashRouter>
      <ContextProvider>
        {element}
      </ContextProvider>
    </HashRouter>
  )
}
Copy the code

The result is wrong!

So, the component that the useRoutes is in must be in the

, so it will work like this:

import { HashRouter, UseRoutes} from 'react-router-dom' import routes from '@/router' function RouteElement() {const element = useRoutes(routes) return element } function App() { return ( <HashRouter> <ContextProvider> <RouteElement /> </ContextProvider> </HashRouter> ) }Copy the code

3. Use rendering child routes in parent components<Outlet>

// v5 import {routes} from 'react-router-config' import routes from './ router-config' function RenderChildren (o) {// Can be props or routes. props:props.route.routes let routes = [] if (Object.prototype.toString.call(o) === '[object Array]') { routes = o } else  if (Object.prototype.toString.call(o) === '[object Object]') { routes = o.route? . Routes | | []} return renderRoutes (routes)} / / UserLayout use react - the router - config renderRoutes to render the function Index (props) { return ( <div className={styles.container}> <div className={styles.content}> {renderChildren(props.route.routes)} // </div> <Footer /> </div>)}Copy the code
/ / v6 directly using the Outlet line / / UserLayout import the React from 'React' import Footer from '@ / components/layout/Footer' import Styles from './index.less' import {Outlet} from 'react-router-dom' // Outlet for rendering children function index () {return () <div className={styles.container}> <div className={styles.content}> <Outlet /> // Here render the child path </div> <Footer /> </div>)}Copy the code

4. Replace all components that use useHistory withuseNavigate

V6 react. lazy implementation

The react. lazy function does not work properly. The react. lazy function does not work properly.

// v5 // routes const routes = [... {path: '/user/login', component: React. Lazy (() = > import (".. / pages/login)) / / routing lazily},... Suspense is in app.jsx, Function App() {return (<HashRouter> <Suspense fallback={<LazyLoading />}> <ContextProvider>{renderChildren(routes)}</ContextProvider> </Suspense> </HashRouter> ); }Copy the code

Suspense is placed at element of routing in V6:

// v6 / routes const Login_lazy = lazy(() => import('@/pages/login')) // v6 // routes const Login_lazy = [... {path: 'login' element: (< Suspense fallback = {< LazyLoading / >} > / / parcel Suspense here < Login_lazy / > < / Suspense >)},... Suspense function App() {return (<HashRouter> <ContextProvider> <RouteElement /> </ContextProvider> </HashRouter> ); }Copy the code

In Suspense, you can use react-router v6 routes to load routes lazily. In Suspense, you can use routes to load routes lazily.

Const routes = [... // BasicLayout {path: 'index1', Element: () => import('@/pages/index1')}, {path: 'index2', element: () => import('@/pages/index2') }, ... ]  function LazyElement(props) { const { importFunc } = props const LazyComponent = lazy(importFunc) return ( <Suspense Fallback ={<div> Route lazy loading... </div>}> < span style > < span style > < span style > Suspense function dealRoutes(routesArr) {if (routesArr && array.isarray (routesArr) && routesarr.length > 0) { routesArr.forEach((route) => { if (route.element && typeof route.element == 'function') { const importFunc = route.element route.element = <LazyElement importFunc={importFunc} /> } if (route.children) { dealRoutes(route.children)  } }) } } dealRoutes(routes) export default routesCopy the code

It looks a little bit more like the old way of writing it, but it’s also a little bit cleaner

At this point, centrally configured routes for React – Router v6 are complete

Ok done!