react-router-dom V6

2023-11-15

目录

1. 前言

2. 变更概览

将 Switch 升级为 Routes

路由匹配组件参数 由 component 改为 element

相对路径识别(子路由不需要补全父路由的path,react会自动补全)

用 useNavigate 替代  useHistory  

废弃 Redirect 标签,使用 Navigate 标签实现路由重定向

优化路由嵌套,添加 outlet 标签

使用 index 标识默认路由

添加 useResolvedPath  hooks 

添加 useSearchParams 读取和设置url参数

link 标签跳转的path 将支持 . 和 .. 这种语法(类比于 terminal 中的 cd .. 返回上级菜单 ) 

 path 通配符将只支持 * 和 :(以前的?等将不再支持) 

添加 useOutletContext 用于 路由之间共享状态


1. 前言

伴随React18的到来,React的路由也有 5.# 版本更新到了 V6版本,接下来让我们总结下 V6 版本的更新内容,对我们的使用有什么影响。

其实官网文档写的很清晰,我这里只是做个总结,大家也可直接移步官网: React Router | Overviewhttps://reactrouter.com/docs/en/v6/getting-started/overview

2. 变更概览

  • 将 Switch 升级为 Routes

  • 路由匹配组件参数 由 component 改为 element

// before V6 
<Switch>
    <Route path="/home" component={Home}></Route>
</Switch>

// V6 
<Routes>
    // 注意,这里是 jsx 语法,需要配合标签, 传参也可以直接写为组件传参
    <Route path="/home" element={<Home animate={true} />}></Route>
</Routes>

  • 相对路径识别(子路由不需要补全父路由的path,react会自动补全)

<Routes>
   <Route path="user" element={<Invoices />}>
       <Route path=":id" element={<Invoice />} />
       <Route path="me" element={<SentInvoices />} />
   </Route>
</Routes>

// path: /user
// path: /user/:id
// path: /user/me
  • 用 useNavigate 替代  useHistory  

// 函数组件使用编程式跳转

// V5
let history = useHistory();
history.push("/home");

// V6
let navigate = useNavigate();
navigate('/home')

// 如果需要类比 history.replace, 可以添加参数replace为true
navigate(to, { replace: true })

// 如果需要类比隐式传参,可以添加参数 state
navigate(to, { state })

// 同时 link 也添加了单独的参数 state
<Link to="/home" state={state} />


// 如果需要类比 goBack,go等语法,也可直接在 navigate中 传层级参数
// 等价于 history.go(-1)
<button onClick={() => navigate(-2)}>
    Go 2 pages back
</button>
<button onClick={() => navigate(-1)}>Go back</button>
<button onClick={() => navigate(1)}>
    Go forward
</button>
<button onClick={() => navigate(2)}>
    Go 2 pages forward
</button>
  • 废弃 Redirect 标签,使用 Navigate 标签实现路由重定向

import { Navigate } from "react-router-dom";

function App() {
  return <Navigate to="/home" replace state={state} />;
}

/*
    v5默认<Redirect />使用 replace 逻辑
    v6默认<Navigate />使用 push 逻辑 ,可以通过参数设置为 replace
*/
  • 优化路由嵌套,添加 outlet 标签

import {
    Routes,
    Route,
    Link,
    Outlet,
    BrowserRouter
  } from "react-router-dom";
  
  function Layout() {
    return (
      <div>
        <h1>Welcome to the V6!</h1>
        <nav>
          <Link to="product">产品页</Link>
          <br/>
          <Link to="detail">详情页</Link>
        </nav>
        <div className="content">
  
          {/* 子路由将会显示在这里,用outlet占位 */}
          <Outlet />
  
        </div>
      </div>
    );
  }
  
  function Product() {
    return <h1>产品页</h1>;
  }
  
  function Detail() {
    return <h1>详情页</h1>;
  }

  function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Layout />}>
                    <Route path="product" element={<Product />} />
                    <Route path="detail" element={<Detail />} />
                </Route>
            </Routes>
        </BrowserRouter>
    );
  }
  
  export default App
  • 使用 index 标识默认路由

<Routes>
   <Route path="/" element={<Layout />}>
       <Route index element={<Activity />} />
       <Route path="invoices" element={<Invoices />} />
       <Route path="activity" element={<Activity />} />
   </Route>
</Routes>
  • 添加 useResolvedPath  hooks 

在 V5版本的文档中,只有四个比较重要的hooks,分别是 useHistory, useLocation, useParams, useRouteMatch,V5文档:

React Router: Declarative Routing for React.jshttps://v5.reactrouter.com/web/api/Hooks/useparams而 V6 版本又添加了一些hooks,我们简单列举几个可能会用到的,完整版移步官网:

https://reactrouter.com/docs/en/v6/api#resolvepathhttps://reactrouter.com/docs/en/v6/api#resolvepath

由于V6的相对路径识别特性,有时我们需要获取完整的url路径,可以使用 useRelovedPath

useRelovedPath 必须接收一个参数,可以为空字符串

  <Route path="/" element={<Layout />}>
       <Route path="product" element={<Product />} />
       <Route path="detail" element={<Detail />} />
  </Route>

  function Product() {
    const path = useResolvedPath('id');
    console.log(path);  // output: { pathname: '/product/id' }
    return <h1>产品页</h1>;
  }
  
  function Detail() {
    const path = useResolvedPath('');
    console.log(path);   // output: { pathname: '/detail' }
    return <h1>详情页</h1>;
  }
  • 添加 useSearchParams 读取和设置url参数

useSerachParams 可以读取和修改当前位置url的查询参数(?id=123), 具体使用方式类比于 useState,但用法略有不同。

获取某个searchParams: searchParams.get(key)

设置某个searchParams: setSearchParams({key:value})

import {
    Routes,
    Route,
    Link,
    Outlet,
    BrowserRouter,
    useResolvedPath,
    useSearchParams
  } from "react-router-dom";
  
  function Layout() {
    return (
      <div>
        <h1>Welcome to the V6!</h1>
        <nav>
          <Link to="product">产品页</Link>
          <Link to="detail?id=123">详情页</Link>
        </nav>
        <div className="content">
  
          <Outlet />
  
        </div>
      </div>
    );
  }
  
  function Product() {
    const path = useResolvedPath('id');
    console.log(path);
    return <h1>产品页</h1>;
  }
  
  function Detail() {
    const [searchParams,setSearchParams] = useSearchParams()

    const handleSubmit = ()=>{
        // 输入键值对,设置对应的 search 参数
        setSearchParams({id:456})
    }

    // 通过 get 方法获取key对应的value
    console.log(searchParams.get('id'));

    return (
        <h1>
            详情页 : {searchParams.get('id')} 
            <br/>
            <button onClick={()=>handleSubmit()}>update searchParams</button>
        </h1>
    );
  }

  function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Layout />}>
                    <Route path="product" element={<Product />} />
                    <Route path="detail" element={<Detail />} />
                </Route>
            </Routes>
        </BrowserRouter>
    );
  }
  
  export default App
  • link 标签跳转的path 将支持 . 和 .. 这种语法(类比于 terminal 中的 cd .. 返回上级菜单 ) 

// 这里直接拿了官网的示例

function App() {
  return (
   <BrowserRouter>
     <Routes>
       <Route path="users" element={<Users />}>
         <Route path=":id" element={<UserProfile />} />
       </Route>
     </Routes>
   <BrowserRouter>

  );
}

function Users() {
  return (
    <div>
      <h2>
        {/* This links to /users - the current route */}
        <Link to=".">Users</Link>
      </h2>

      <ul>
        {users.map((user) => (
          <li>
            {/* This links to /users/:id - the child route */}
            <Link to={user.id}>{user.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

function UserProfile() {
  return (
    <div>
      <h2>
        {/* This links to /users - the parent route */}
        <Link to="..">All Users</Link>
      </h2>

      <h2>
        {/* This links to /users/:id - the current route */}
        <Link to=".">User Profile</Link>
      </h2>

      <h2>
        {/* This links to /users/mj - a "sibling" route */}
        <Link to="../mj">MJ</Link>
      </h2>
    </div>
  );
}
  •  path 通配符将只支持 * 和 :(以前的?等将不再支持) 

// 这里直接拿了官网的例子,让我们看下 * 的作用(子孙路由)
import {
  BrowserRouter,
  Routes,
  Route,
  Link,
} from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="users/*" element={<Users />} />
      </Routes>
    </BrowserRouter>
  );
}

function Users() {
  return (
    <div>
      <nav>
        // path: user/me
        <Link to="me">My Profile</Link>
      </nav>

      <Routes>
        // path:  user/:id
        <Route path=":id" element={<UserProfile />} />

        // path:  user/me
        <Route path="me" element={<OwnUserProfile />} />
      </Routes>
    </div>
  );
}
  • 添加 useOutletContext 用于 路由之间共享状态

我们可以用 useOutletContext 在子路由与父路由之间共享一些值

function Parent() {
  const [count, setCount] = React.useState(0);
  return <Outlet context={[count, setCount]} />;
}


import { useOutletContext } from "react-router-dom";

function Child() {
  const [count, setCount] = useOutletContext();
  const increment = () => setCount((c) => c + 1);
  return <button onClick={increment}>{count}</button>;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

react-router-dom V6 的相关文章

  • Sonar 中的 javascript 代码覆盖率

    我是使用 Sonar 和插件进行 javascript 代码覆盖的新手 使用 Sonar 分析时 有哪些可能性可以找出 javascript 代码的质量 包括代码覆盖率 目前我正在使用 karma runner 它提供代码覆盖率报告 可以在
  • 无法读取未定义的“触及”属性

    为什么我会收到此错误无法读取未定义的属性 为什么无法读取formName controls email touched但它能够阅读formName get custDetails touched
  • 限制 Dropzone 仅上传特定类型的文件

    我正在使用 Dropzone 上传文件 这是我的代码 div div
  • 游戏手柄 JavaScript 未能按预期更新

    我正在尝试让浏览器报告我的 XBOX 控制器的状态 然而 在第一次按下按钮后 它似乎变得 卡住 我究竟做错了什么
  • html canvas动画卡顿

    谁能解释为什么提供的画布动画断断续续 我创建了一个测试存根来演示该问题 我在桌面上的 FF Chrome IE 以及 Android 上的 FF 和 Chrome 中看到了卡顿现象 口吃是由于垃圾收集造成的吗 似乎 raf 在每次调用时都会
  • JavaScript:常量属性

    在javascript中 我可以将对象的属性声明为常量吗 这是一个示例对象 var XU Cc Components classes or function aXU this Cc Components classes var XU new
  • 将异步事件监听器与 Nestjs EventEmitter 模块和无服务器函数结合使用

    我正在尝试在 Nestjs EventEmitter 模块的帮助下实现具有无服务器 lambda 函数的异步工作线程 处理程序在发出事件时被调用 但该函数在 async await 调用之前关闭 我尝试过同时使用emit and emitA
  • 在react-admin中通过REST API进行基于cookie的身份验证

    我是反应管理新手 我已经阅读了 stackoverflow 中的所有问题 也用谷歌搜索了我的问题 但没有找到任何有用的解决方案 我正在设置 React admin 来替换我的一个项目的现有管理页面 我通过 REST API 使用基于 coo
  • 避免在 ES6 的函数内定位 this 的对象作用域

    例如 我正在使用 D3 js 运行一个项目 导入特定模块并调用它们的函数 Setup TypeScript ES6 导入特定的 D3 组件 角6 我有一个对象 在本例中是一个角度指令 并在 SVG 画布上绘制一些圆圈 并希望它们在拖动事件上
  • 带有 mkdocs 的本地 mathjax

    我想在无法访问互联网的计算机上使用 MathJax 和 Mkdocs 因此我不能只调用 Mathjax CDN Config mkdocs yml site name My Docs extra javascript javascripts
  • 有没有办法伪造同步 XHR 请求?

    我正在使用 Emscripten 系统将一堆 C 代码移植到 Javascript C 代码有很多调用fopen这是一个同步 IO 调用 在 Emscripten 中 我们使用对本地资源的 XHR 请求来模拟这一点however 在 Fir
  • 如何使用Create React App安装React

    嗨 我对反应真的很陌生 我不知道如何实际安装它 也不知道我需要做什么才能在其中编写代码 我下载了node js并且安装了v12 18 3以及NPM 6 14 6 但是每次我尝试在许多网站上提到的create react app安装方法中输入
  • 如何使用 JavaScript 获取元素的填充值?

    我有一个textarea在我的 HTML 中 我需要获取整数或浮点形式的填充数值 以像素为单位 我如何使用 JavaScript 获取它 我没有使用 jQuery 所以我正在寻找纯 JavaScript 解决方案 这将返回padding l
  • JavaScript 中的实时摩尔斯电码转换器

    在看到谷歌关于莫尔斯电码 gmail 的愚人节笑话后 我想我应该尝试用 javascript 创建一个实时莫尔斯电码转换器 我正在使用正则表达式和替换将莫尔斯电码更改为字符 例如 replace g a replace g r 我遇到的问题
  • JavaScript 提升解释

    下面的片段有什么区别 var a 0 function b a 10 return function a b console log a gt 10 and var a 0 function b a 10 return function a
  • 使用 AJAX 和 JQuery 按设定的时间间隔刷新 Rails 部分

    I have a page in my rails application that looks like 现在 我有另一个用 python 编码的人工智能应用程序 它处理视频 显示在 Rails 应用程序页面的左侧 并使用捕获的车辆及其相
  • 检测浏览器选项卡是否具有焦点

    是否有可靠的跨浏览器方法来检测选项卡是否具有焦点 场景是 我们有一个定期轮询股票价格的应用程序 如果页面没有焦点 我们可以停止轮询并为每个人节省流量噪音 特别是当人们喜欢打开具有不同投资组合的多个选项卡时 Is window onblur
  • 具有固定顶部菜单的语义 UI 侧边栏

    Semantic UI 对其进行预警侧边栏页面 http semantic ui com modules sidebar html usage 当侧边栏出现时 固定位置内容可能会出现改变其位置的问题 然后它提供了该问题的两种可能的解决方案
  • D3 将现有 SVG 字符串(或元素)追加(插入)到 DIV

    我到处寻找这个问题的答案 并找到了一些我认为可能有用的资源 但最终没有让我找到答案 这里有一些 外部SVG http bl ocks org mbostock 1014829 嵌入SVG https stackoverflow com qu
  • 用javascript调用外部网页(跨域)

    我正在尝试使用以下网络服务来验证提要这个问题 https stackoverflow com questions 11996430 check if a url is a valid feed 但浏览器不允许我向另一台服务器发送 ajax

随机推荐

  • ethercard php_关于EtherCard的webClient代码分析

    以下代码摘自EtherCard的webClient实例 主要功能是打开指定网址 Serial print const char Ethernet buffer off 这一行显示服务器返回的数据 当输出一个没有任何格式的页面的时候 也返回一
  • 稳压二极管(齐纳Zener二极管)的接法和应用详解

    http www elecfans com dianzichangshi 20170529520260 html http www elecfans com yuanqijian erjiguang 20180103610356 html
  • Zabbix学习笔记(二)Zabbix的配置

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 目录 前言 1 数据库设置 2 zabbix 服务器设置 1 访问并配置zabbix 总结 前言 近期学习网络运维监控方面的知识 在使用Zabbix系统中遇到了许多的问题 在
  • 深入理解CSS中em, rem, ex区别,及使用技巧

    CSS 中常见尺寸 单位 描述 百分比 in 英寸 cm 厘米 mm 毫米 ex 一个 ex 是一个字体的 x height x height 通常是字体尺寸的一半 pt 磅 1 pt 等于 1 72 英寸 pc 12 点活字 1 pc 等
  • 华为三层交换机VRRP与DHCP综合实验

    要求设计 1 公司有三个部门 为确保通信安全 每个部门都处于独立的广播域 2 Vlan40为外来人员所在的Vlan 此vlan中的主机只能访问DHCP服务器 3 每个部门的 IP地址规划为 192 168 xx 0 24 4 每个部门的主机
  • 【前端】Vue项目:旅游App-(18)TabBar:debug,非点击tabBar的路由跳转active显示问题

    文章目录 目标 过程与代码 原因与属性的添加 currentIndex的修改 效果 总代码 修改的文件 tab bar vue 本项目博客总结 前端 Vue项目 旅游App 博客总结 目标 当我们在url处实现路由跳转时 tabBar没有产
  • java程序语句_Java-语言编程

    创建节点和插入节点 很多时候我们想要在某个位置插入一个新的节点 此时我们首先需要有一个节点存在 可以通过以下几种方式创建新节点 创建节点 方法描述createElement 创建一个新的节点 需要传入节点的标签名称 返回创建的元素对象cre
  • 100天精通Python(数据分析篇)——第74天:Panda索引标签修改函数大全(参数说明+代码实战)

    文章目录 本文导读 一 添加标签前后缀 1 add prefix str 2 add suffix str 二 标签重命名 1 set axis 1 修改行标签 2 修改列标签
  • oracle统计信息详解

    收集oracle统计信息 优化器统计范围 表统计 行数 块数 行平均长度 all tables NUM ROWS BLOCKS AVG ROW LEN 列统计 列中唯一值的数量 NDV NULL值的数量 数据分布 DBA TAB COLUM
  • RGMII Delay的一点理解

    RGMII delay 如何产生的 可能是RGMII协议规定如此 因此在soc内部集成的RGMII片内外设 将时钟边沿与数据跳变在同一时刻发生 但是RGMII接收端是需要在时钟的边沿处捕获数据的 因此就需要将发送时钟移位 进而使接收端可以正
  • js 数组id去重

    可以用下面的方法来去除数组中的重复项 先将数组转换为 Set 类型 然后再转回数组 这种方法的缺点是会丢失原数组的顺序 const arr 1 2 3 3 2 1 const unique new Set arr console log u
  • C语言PTA题目:7-22 1022 利息

    输入存款金额money 存期year和年利率rate 根据下列公式计算存款到期时的利息interest 税前 输入格式 输入可能有多行 每行有3个整数 分别表示金额 存期 年 年利率 百分比数 输出格式 根据money 1 rate yea
  • 服务器怎么把自己的项目放上去,怎么把项目放到云服务器上

    怎么把项目放到云服务器上 内容精选 换一换 云服务器组是对云服务器的一种逻辑划分 云服务器组中的弹性云服务器遵从同一策略 当前仅支持反亲和性 即同一云服务器组中的弹性云服务器分散地创建在不同的主机上 提高业务的可靠性 您可以使用云服务器组将
  • 微信小程序:字体保持大小

    小程序和网页差不多 前台用wxml把内容摆好 然后用css调整样式 所以和web一样 必须要能够精确控制每一个元素的大小 在Web中 通过CSS基本达到了像素级的控制 但在小程序中 情况有所不同 下面是我通过微信提供的事件分析 把近7天访问
  • 数字化转型方法论汇总(学习笔记)

    数字化转型方法论汇总 德勤制造业数字化转型方法论 数字化转型的3大要点 1 从满足利益相关者期望出发 2 以企业价值引领业务模式创新 3 以信息作为企业神经中枢 重塑组织协同 一 关注集团利益相关者 两类利益相关者 集团外部的证监会 国资委
  • 比较2个数组是否一样

    需求 如果两个数组的类型 元素个数 元素顺序和内容是一样的我们就认为这2个数组是一模一样的 请使用方法完成 能够判断任意两个整型数组是否一样 并返回true或者false 分析 1 定义方法 接收2个整型数组 gt 是否需要参数 返回值类型
  • 《Win10——如何进入高级启动选项》

    Win10 如何进入高级启动选项 第一种方法 1 管理员命令提示符输入如下代码 自动重启并进入高级启动选项 shutdown r o f t 00 第二种方法 1 管理员命令提示符输入以下代码 开机时按下F8 进入高级启动选项 bcdedi
  • java基础总结(二十五)--访问修饰符protected

    三 protected 关键字的真正内涵 很多介绍Java语言的书籍 包括 Java编程思想 都对protected介绍的比较的简单 基本都是一句话 就是 被protected修饰的成员对于本包和其子类可见 这种说法有点太过含糊 常常会对大
  • 基于python 自写Tobii VI-T滤波器

    文章目录 官网参考文档 Gap fill in interpolation Eye selection Noise reduction Velocity calculator I VT classifier Merge adjacent f
  • react-router-dom V6

    目录 1 前言 2 变更概览 将 Switch 升级为 Routes 路由匹配组件参数 由 component 改为 element 相对路径识别 子路由不需要补全父路由的path react会自动补全 用 useNavigate 替代 u