{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. useHistory
No, use ituseNavigate
Instead, 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, newuseRoutes
Can 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, use
element: <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,useRoutes
Put 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!