相关文章推荐
不开心的小蝌蚪  ·  java.lang.UnsatisfiedL ...·  2 月前    · 
忐忑的黑框眼镜  ·  system verilog - ...·  1 年前    · 

React-router新特性详解

5 个月前 · 来自专栏 xiangzhihong的专栏

由于之前的项目一直使用的是V5版本,最新新建项目的时候,默认使用的是V6版本,根据官方的介绍,V6版本的新特性如下。

新特性

  • <Switch> 重命名为 <Routes>
  • <Route> 的新特性变更;
  • 嵌套路由变得更简单;
  • 新钩子useRoutes代替react-router-config;
  • 用useNavigate代替useHistory;
  • Link不再支持component 属性;
  • NavLink的exact属性替换为end
  • 大小减少:从20kb到8kb

<Switch> 重命名为 <Routes>

在V6版本中, <Switch> 组件被替换成 <Routes> 组件,同时,component属性被element属性替换。

/* v5 */
<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/user/:id" render={(routeProps) => <User id={routeProps.match.params.id} />} />
</Switch>
/* V6 */
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="user/:id" element={<User id={id} />} />
</Routes>

同时,组件还修改了如下一些内容: - 废弃exact - component/render被element替代 - routeProps可以在element中直接获取 - 简化的路径匹配,仅支持动态:id样式参数和*通配符,不再支持RegExp

支持嵌套路由

在V6版本中, <Route> 标签支持嵌套,可以在一个文件内配置嵌套路由,便于统一管理路由。

import { HashRouter as Router, Routes, Route } from 'react-router-dom'
import Home from '@/pages/demo/Home'
import Foo from '@/pages/demo/Foo'
import Bar from '@/pages/demo/Bar'
import BarDetail from '@/pages/demo/BarDetail'
import '@/assets/style/App.css'
function App() {
 return (
   <Router>
     <Routes>
       <Route path="/" element={<Home />} />
       <Route path="foo" element={<Foo />} />
       {/* 嵌套路由场景:需要在Bar(父路由的组件)声明Outlet组件,用于渲染子路由 */}
       <Route path="bar" element={<Bar />}>
         <Route path=":id" element={<BarDetail />} />
       </Route>
     </Routes>
   </Router>
export default App

Outlet

在嵌套路由场景,我们需要在父路由中使用Outlet组件,用于渲染子路由。

import { Outlet } from 'react-router-dom'
function Bar() {
  return (
      <div>Bar</div>
      {/* 有嵌套路由的场景需要使用 */}
      <Outlet />
export default Bar

嵌套路由可配置化

在V6版本中,我们可以使用useRoutes代替react-router-config配置。如果需要用到嵌套路由,那么Outlet组件也是必要的。

import { useRoutes } from 'react-router-dom'
import Home from '@/pages/demo/Home'
import Foo from '@/pages/demo/Foo'
import Bar from '@/pages/demo/Bar'
import BarDetail from '@/pages/demo/BarDetail'
import '@/assets/style/App.css'
function App() {
  let element = useRoutes([
      path: '/',
      element: <Home />
      path: 'foo',
      element: <Foo />
      path: 'bar',
      element: <Bar />,
      children: [
          path: ':id',
          element: <BarDetail />
  return element
export default App

需要注意的是,如果是使用此方式注册路由配置,需要在入口文件添加Router包裹App组件,否则会报错。

import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter as Router } from 'react-router-dom'
import App from '@/App'
import '@/assets/style/index.css'
ReactDOM.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
)

useNavigate代替useHistory

/* v5 */
const history = useHistory()
history.push('/home')
history.replace('/home')
history.goBack()
history.goForward()
history.go(2)
/* V6 */
const navigate = useNavigate()
navigate('/home')
navigate('/home', {replace: true})
navigate(-1)
navigate(1)
navigate(2)

路由穿参

路由传参主要有三种方式:params、search和state。

1,useParams

useParams的路由格式为: /home/12

<Routes>
    <Route path="/" element={<Admin />} >
        <Route path="home" element={<Home />} >
            <Route path=":id" element={<HomeSon />} />
        </Route>
    </Route>
</Routes>
// HomeSon页面,读取参数
import React from 'react';
import { useParams } from 'react-router-dom';
const HomeSon = () => {
    // id 就是传过来的参数 id就是12
    let { id } = useParams();
    return (
            这是HomeSon页面 {id}
export default HomeSon;

2, useSearchParam

useSearchParam的路由格式为: /home?id=1。

<Routes>
    <Route path="/" element={<Admin />} >
        <Route path="user" element={<User />} ></Route>
    </Route>
</Routes>
<NavLink to="/user?id=1" style={({ isActive }) =>
              isActive ? activeStyle : undefined
User</NavLink>
// User页面
import React from 'react';
import { useSearchParams } from 'react-router-dom';
const User = () => {
    let [searchParams] = useSearchParams();
    const id = searchParams.get('id'); // id为参数值
    return (
        <div>这是user页面</div>
export default User;

3,state

state在地址栏看不见参数,使用useLocation方法获取参数。

// state定义id为1
  style={{
      borderBottom: "solid 1px",
      paddingBottom: "1rem"
  <NavLink to='/state' state={{ id: 1  }}>State</NavLink>
// state页面
import { useLocation } from 'react-router-dom';
const State = () => {
    const {state} = useLocation();
    console.log(state); // { id: 1 }
    return (
        <div style={{ display: "flex" }}>
            <div>这是State组件</div>
                {state}