React-Router V6 使用详解

2023-11-19

一、基本用法

React-Router的安装方法:

npm: $ npm install react-router-dom@6

yarn$ yarn add react-router-dom@6

目前官方从5开始已经放弃原有的react-router库,统一命名为react-router-dom
复制代码

使用方法

React-Router本身在React开发中就是一个组件,因此在使用时基本遵循组件开发相关原则。这里采用create-react-app来创建一个基础的demo工程演示使用过程。
复制代码
  1. 创建demo create-react-app my-first-react

    安装react-router组件

  2. 启用全局路由模式

    全局路由有常用两种路由模式可选:HashRouter 和 BrowserRouter HashRouter:URL中采用的是hash(#)部分去创建路由,类似
    www.example.com/#/BrowserRouter:URL采用真实的URL资源 后续有文章会详细讲HashRouter的原理和实现,这里我们采用BrowserRouter来创建路由

    index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import reportWebVitals from './reportWebVitals';
    import { BrowserRouter } from 'react-router-dom';
    
    ReactDOM.render(
      <React.StrictMode>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    reportWebVitals();
    复制代码

    这样我们在yarn start 或者 npm run start的时候访问/就可以访问这个组件了,具体效果大家可以自行运行

  3. 路由功能 React-Router V6版本常用路由组件和hooks,其他不常用的大家可以看下官网的介绍

    组件名 作用 说明
    <Routers> 一组路由 代替原有<Switch>,所有子路由都用基础的Router children来表示
    <Router> 基础路由 Router是可以嵌套的,解决原有V5中严格模式,后面与V5区别会详细介绍
    <Link> 导航组件 在实际页面中跳转使用
    <Outlet/> 自适应渲染组件 根据实际路由url自动选择组件
    hooks名 作用 说明
    useParams 返回当前参数 根据路径读取参数
    useNavigate 返回当前路由 代替原有V5中的 useHistory
    useOutlet 返回根据路由生成的element
    useLocation 返回当前的location 对象
    useRoutes 同Routers组件一样,只不过是在js中使用
    useSearchParams 用来匹配URL中?后面的搜索参数
    基础使用示例

    App.js

    这里创建了两个组件Home和About,然后分别注册/和about,在每个页面还有Link来进行导航
    复制代码
    import './App.css';
    import { Routes, Route, Link } from "react-router-dom"
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <Routes>
              <Route path="/" element={<Home />}></Route>
              <Route path="/about" element={<About />}></Route>
            </Routes>
          </header>
        </div>
      );
    }
    function Home() {
      return <div>
        <main>
          <h2>Welcome to the homepage</h2>
        </main>
        <nav>
          <Link to="/about">about</Link>
        </nav>
      </div>
    }
    function About() {
      return <div>
        <main>
          <h2>Welcome to the about page</h2>
        </main>
        <nav>
          <ol>
            <Link to="/">home</Link>
            <Link to="/about">about</Link>
          </ol>
    
        </nav>
      </div>
    }
    export default App;
    
    复制代码

    运行后

    image.png

    image.png

    至此,一个最简单的路由demo就正常运行了。

  4. 嵌套路由

    嵌套路由是V6版本对之前版本一个较大的升级,采用嵌套路由会智能的识别

    function App() {
      return (
        <Routes>
          <Route path="user" element={<Users />}>
            <Route path=":id" element={<UserDetail />} />
            <Route path="create" element={<NewUser />} />
          </Route>
        </Routes>
      );
    }
    复制代码

    当访问 /user/123 的时候,组件树将会变成这样

    <App>
        <Users>
            <UserDetail/>
        </Users>
    </App>
    复制代码

    当访问/user/create的时候,组件树将变成这样

    <App>
       <Users>
           <NewUser/>
       </Users>
    </App>
    复制代码

    如果只是内部组件修改,也可以采用<Outlet/>来直接实现,如下所示

    function App() {
      return (
        <Routes>
          <Route path="user" element={<Users />}>
            <Route path=":id" element={<UserDetail />} />
            <Route path="create" element={<NewUser />} />
          </Route>
        </Routes>
      );
    }
    function Users() {
      return (
        <div>
          <h1>Users</h1>
          <Outlet />
        </div>
      );
    }
    复制代码
  5. index路由

    index属性解决当嵌套路由有多个子路由但本身无法确认默认渲染哪个子路由的时候,可以增加index属性来指定默认路由

    function App() {
      return (
        <Routes>
          <Route path="/" element={<Layout />}>
            <Route index element={<About />} />
            <Route path="user" element={<User />} />
            <Route path="about" element={<About />} />
          </Route>
        </Routes>
      );
    }
    复制代码

    这样当访问/的时候<Outlet/>会默认渲染About组件

  6. 路由通配符

    整个react-router支持以下几种通配符
    复制代码
    /groups
    /groups/admin
    /users/:id
    /users/:id/messages
    /files/*
    /files/:id/*
    复制代码

    注意,以下这些正则方式在V6里面是不支持的

    /users/:id?
    /tweets/:id(\d+)
    /files/*/cat.jpg
    /files-*
    复制代码

    这里的*只能用在/后面,不能用在实际路径中间

    关于NotFound类路由,可以用*来代替

    function App() {
      return (
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="dashboard" element={<Dashboard />} />
          <Route path="*" element={<NotFound />} />
        </Routes>
      );
    }
    复制代码
  7. 获取参数 useParams 和useSearchParams

    假设现有App路由

    function App() {
     return (
       <Routes>
         <Route path="user" element={<Users />}>
           <Route path=":id" element={<UserDetail />} />
           <Route path="create" element={<NewUser />} />
         </Route>
       </Routes>
     );
    }
    复制代码

    那么在UserDetail内部需要用useParams来获取对应的参数

    import { useParams } from "react-router-dom";
    
    export default function UserDetail() {
      let params = useParams();
      return <h2>User: {params.id}</h2>;
    }
    复制代码

    useSearchParams相对复杂,他返回的是一个当前值和set方法

    let [searchParams, setSearchParams] = useSearchParams();

    使用时可以用searchParams.get("id")来获取参数,同时页面内也可以setSearchParams({"id":2})来改变路由,这样当访问 http://URL/user?id=111时就可以获取和设置路径

  8. useNavigate

    useNavigate是替代原有V5中的useHistory的新hooks,前端培训​​​​​​​其用法和useHistory类似,整体使用起来更轻量,他的声明方式如下:

    declare function useNavigate(): NavigateFunction;
    
    interface NavigateFunction {
      (
        to: To,
        options?: { replace?: boolean; state?: State }
      ): void;
      (delta: number): void;
    }
    复制代码
      //js写法
      let navigate = useNavigate();
      function handleClick() {
        navigate("/home");
      }
      //组件写法
      function App() {
         return <Navigate to="/home" replace state={state} />;
      }
      //替代原有的go goBack和goForward
     <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>
    复制代码

二、与V5的区别

1.用<Routes> children形式替代<Switch>

V5写法:

 function App() {
   return (
     <Switch>
       <Route exact path="/">
         <Home />
       </Route>
       <Route path="/about">
         <About />
       </Route>
       <Route path="/users/:id" children={<User />} />
     </Switch>
   );
 }
复制代码

V6写法

 function App() {
   return (
     <Routes>
       <Route index path="/" element={<Home />} />
       <Route path="about" element={<About />} />
       <Route path="/users/:id" element={<User />} />
     </Routes>
   );
 }
复制代码

2.去除Switch中的<Redirect>,用react-router-dom中的Redirect 替代,或者用 <Navigate> 实现

V5写法:

 <Switch>
   <Redirect from="about" to="about-us" />
 </Switch>
复制代码

V6写法:

 <Route path="about" render={() => <Redirect to="about-us" />}
复制代码

3.<Link to>支持相对位置

V5版本的to属性只支持绝对位置,如<Lint to="me">表示<Lint to="/me">,如果当时正在Users组件内,想跳转需要<Lint to="/users/me">。在V6中,Link默认支持相对位置,也就是<Lint to="me"> 在Users组件内会等价于<Lint to="/users/me">,同时支持'..' 和'.'等相对路径写法。

// If your routes look like this
<Route path="app">
<Route path="dashboard">
 <Route path="stats" />
</Route>
</Route>

// and the current URL is /app/dashboard (with or without
// a trailing slash)
<Link to="stats">               => <a href="/app/dashboard/stats">
<Link to="../stats">            => <a href="/app/stats">
<Link to="../../stats">         => <a href="/stats">
<Link to="../../../stats">      => <a href="/stats">
复制代码

4.使用useNavigate代替useHistory

可以参考上面useNavigate使用,这里不再赘述

总结

V6版本的react-router升级了原有嵌套路由写法,并且重新实现了useNavigate来替代useHistory,整体上更加好理解。当然还有些其他属性和方法没有再介绍,大家如果有其他想知道的也可以回复我来补充。

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

React-Router V6 使用详解 的相关文章

  • 将 Javascript 变量转换为 PHP 变量

    我想使用由 videoel getCurrentTime 函数返回给我的 javascript 变量 并将其转换为 php 变量 以便我能够将其添加到我的 SQL 插入查询中 例如 INSERT INTO tblData VALUES ph
  • React 渲染中的不变违规或 React 中迭代和返回的正确方法

    我在 React 渲染中遇到了持续存在的问题 这段代码 jsx React DOM var AnswerRows React createClass componentDidMount function render function th
  • 如何使用 LinkedIn javascript sdk 检索包括所有字段的职位列表?

    我想要获取 LinkedIn 会员在其个人资料中输入的每个职位的 ID 头衔 摘要 开始日期 结束日期 当前状态和公司名称 我测试了一个查询休息控制台 https apigee com console linkedin我得到了想要的结果 查
  • compose 未从react-apollo 导出

    我正在关注 youtube 上的 graphql 教程 https www youtube com watch v ed8SzALpx1Q https www youtube com watch v ed8SzALpx1Q大约3小时16分钟
  • 通过 SVG 背景传递鼠标事件

    我有两个 SVG 元素 每个元素覆盖整个屏幕 html body height 100 svg position absolute top 0 left 0 bottom 0 right 0
  • 未捕获的类型错误:this.props.signinUser 不是一个函数(…)

    src actions index js import axios from axios const ROOT URL http localhost 3090 export function signinUser email passwor
  • JavaScript 变量赋值与 OR 对比 if 检查[重复]

    这个问题在这里已经有答案了 在 JavaScript 中 我最近意识到你可以使用 OR 赋值的逻辑运算符 我想知道这是否被认为是不好的做法 特别是 我有一些具有可选数组输入的函数 如果输入是null or undefined我应该将它设置为
  • 为什么将数据存储为元素的属性存在风险?

    我一直在读同样的东西 直接在 DOM 元素上存储属性值是有风险的 因为可能会发生内存泄漏 但有人可以更详细地解释这些风险吗 按属性 我假设您指的是 DOM 元素上的属性 DOM 元素上的自定义属性安全吗
  • 从未定义解构时避免错误

    可以说我有这个代码 const x y point Babel 会将其变成 var point point x point x y point y 这很好 但是如果点未定义怎么办 现在我得到一个错误 Cannot read property
  • 在 Angular2 项目中集成 Treant-js

    我正在尝试在 Angular2 项目中使用 treant js 但我正在努力解决如何正确集成它的问题 我有一个工作正常的 JavaScript HTML 示例 我正在尝试在 Angular2 中工作 我创建了一个组件 从 npm 添加了 t
  • Telegram 授权无默认按钮

    使用 Telegram 第 3 方授权的唯一有记录的方法是使用其提供的脚本https core telegram org widgets login https core telegram org widgets login 这个脚本 正如
  • 光滑的轮播缓动示例

    我正在使用 Slick Carousel http kenwheeler github io slick http kenwheeler github io slick 但不知道如何合并不同的幻灯片切换 有人有例子可以分享吗 这是我目前拥有
  • 将 NPM 包客户端与 nuxt 结合使用

    我对 nuxt 和 javascript 非常陌生 我正在尝试弄清楚如何在客户端使用我的应用程序的依赖项 我将它们列在我的 nuxt config js 中并使用 npm 安装 我也有一个文件 plugins导入它们的目录 不确定这是否好
  • Javascript 选择 onchange='this.form.submit()'

    我有一个带有选择和一些文本输入的表单 我希望在更改选择时提交表单 使用以下方法可以正常工作 onchange this form submit 但是 如果表单还包含提交按钮 则当选择更改时 表单不会提交 我猜有某种冲突 我在这里有什么选择
  • Postman - 如何计算 JSON 响应中特定对象的出现次数

    我是 JSON 和 Postman 的新手 我相信我正在尝试做一些非常简单的事情 我创建了一个 GET 请求 它将获得如下所示的 JSON 响应 在下面的例子中我想得到count响应中所有 IsArchived 属性 这些属性的数量因响应而
  • 如何在粘贴时获取文本区域输入字段的新值?

    我发现当我尝试从文本区域字段读取值时onpaste调用函数时 我得到字段的旧值 粘贴操作之前的值 而不是新值 粘贴操作之后的值 以下是此行为的演示 http jsfiddle net qsDnr http jsfiddle net qsDn
  • 在声明组件选择器时添加指令 - Angular 7

    我正在学习 Angular 并通过单击按钮动态创建组件 我正在尝试使用 Angular Material 的拖放功能来拖动这些创建的组件以对它们进行排序 我的基本组件 html 中有以下代码 div style margin 20px di
  • 从 Firebase 实时数据库 + 存储加载图像

    我正在使用 Firebase 文档 react redux firebase 中的 create react app 创建类似汽车图片库的东西 图像信息存储在 Firebase 实时数据库中 但实际图像文件存储在 Firebase 存储中
  • 错误:创建 React Native 项目版本 0.59.9 时找不到 template.config.js

    当我尝试创建 React Native 项目版本 0 59 9 时 出现以下错误 错误错误 无法在 react native 模板中找到 var folders zc h93bvpb573q24 5ynvgkn1wc0000gn T rnc
  • Serviceworker Bug event.respondWith

    我的 serviceworker 的逻辑是 当发生获取事件时 它首先获取包含一些布尔值 而不是 event request url 的端点 并根据我正在调用的值检查该值event respondWith 对于当前的获取事件 我正在提供来自缓

随机推荐

  • 离散数学模拟微信红包算法升级版

    可以自定义红包总金额 总包数 每包最小金额
  • 关于springboot的序列化和反序列化问题

    在springboot中有时候需要将Datatime的格式进行格式化 有时候Long型的数据超过16位传值到前端js中会丢失精度 解决这个问题需要将Long型先转为String类型在传值到前端 所以可以编写实现类继承ObjectMapper
  • PicoNeo3开发VR——小白教程

    不断更新中 欢迎大佬们来指导 纠错 导入PicoVRSDK 1 新创一个Unity工程 Unity版本最好选择2019 4以上版本 以及需配置好安卓环境 然后导入官方picoVRSDK 2 渲染设置 Graphics APIs暂不支持Vul
  • DirectShow系列讲座之二——Filter原理

    在上一讲中 笔者介绍了DirectShow的总体系统框架 从这一讲开始 我们要从程序员的角度 进一步深入探讨一下DirectShow的应用以及Filter的开发 在这之前 笔者首先要特别提一下微软提供的一个Filter测试工具 GraphE
  • SpringBoot 高级进阶

    目录标题 SpringBoot 高级 1 RabbitMQ概述 1 RabbitMQ简介 消息服务中两个重要概念 消息队列主要有两种形式的目的地 异步处理 应用解耦 流量削峰 核心概念 2 RabbitMQ运行机制 3 RabbitMQ安装
  • 分布式部署 Zabbix 监控平台

    分布式部署 Zabbix 监控平台 一 基本介绍 二 部署 LNMP 架构 1 配置 MySQL 服务 2 配置 Nginx PHP 服务 1 安装 Nginx 2 安装 PHP 3 修改 PHP 配置文件 4 启动脚本 三 部署 Zabb
  • 跨站脚本攻击XSS(最全最细致的靶场实战)

    一 XSS跨站漏洞 1 XSS简介 网站中包含大量的动态内容以提高用户体验 比过去要复杂得多 所谓动态内容 就是根据用户环境和需要 Web应用程序能够输出相应的内容 动态站点会受到一种名为 跨站脚本攻击 Cross Site Scripti
  • 教你如何快速下载python

    1 打开python官网 链接 py官网 2 找到自己要安装的版本 点击下载 3 下载 exe文件 打开 4 弹出标题为Install Python X X X X bit 的窗口 将下面的Add Python 打勾 点Install No
  • (一)软件架构概述

    1 系统结构 B S架构 Browser Server 浏览器 服务器的交互形式 Browser支持哪些语言 HTML CSS JavaScript 写HTML CSS JavaScript代码的这波人职位叫做 WEB 前端开发工程师 Ja
  • Python学习笔记(四)

    文章目录 1 进程 1 1 系统原生 OS 模块 创建进程 1 2 multiprocessing 模块 1 2 1 Process 单进程 1 2 2 Pool 进程池 1 3 subprocess 模块 使用外部子进程 2 线程 2 1
  • 爬虫 跨域请求 获取json数据 解决参数加密

    分析网址 提示 抓取对方信息是通过对方允许的 请不要违法操作 抓取其他个人有关信息 网址先发送了一个OPTIONS请求 Request URL http xxxxxxxx com Request Method OPTIONS Status
  • C++知识积累:内存对齐理解

    为什么要进行内存对齐 这是因为CPU的读取总是对齐的 举个例子 假设CPU是32位的 那么CPU每次读取的4字节数据的首地址都是4的倍数 也就是说 内存中数据首地址为4的倍数时 CPU一次操作就可以完成数据读取 假设有一个int型四字节大小
  • 警告: Can't initialize javac processor due to (most likely) a class loader problem: java.lang.NoClassD

    说明 主要参考了这位大佬的文章 https www cnblogs com xxjcai p java compiler html 不过我是在使用IDEA的时候遇到的问题 所以我这里介绍一下在IDEA中的解决方案 错误信息 src main
  • VS2017 NuGet包管理

    一 在 https www nuget org 注册账号并生成APIKEY 二 在命令行窗口启动nuget exe 三 生成 nuspec文件 将nuget exe放置在项目目录 注意下图 处的id version 打包后会生成 id ve
  • C/C++ int a[]和int (*a)[]的区别

    int a a与 先结合 a为数组 数组element type int int a a与 先结合 a为指针 指向数组 同int a link https www jianshu com p 548ff8e1b243
  • CentOS7修改SSH端口

    CentOS7 修改SSH端口 文章目录 CentOS7 修改SSH端口 1 修改ssh配置文件 1 1 查看默认端口 1 2 修改端口 2 防火墙放行 2 1 查看防火墙状态 2 2 防火墙放行端口 202 2 3 查看已开启端口 2 4
  • svn客户端检出的工程导入eclipse后不显示SVN信息

    1 首先确定原因 是由于SVN客户端与SVN插件版本不对应导致的 因此需要更换SVN插件版本 1 1 SVN插件与SVN客户端版本对应关系 插件svn1 4 x对应TortoiseSvn 1 5 x 插件svn1 6 x对应Tortoise
  • Keil MDK编程环境下的 STM32 IAP下载(学习笔记)

    IAP下载 IAP的引入 不同的程序下载方式 ICP ICP In Circuit Programing 在电路编程 可通过 CPU 的 Debug Access Port 烧录代码 比如 ARM Cortex 的 Debug Interf
  • Jsp页面java.lang.NumberFormatException: For input string: ““错误解决办法

    Jsp页面报Java lang NumberFormatException For input string 错误解决办法 昨天写代码遇到一个错误 在日志和控制台报一个错误说jsp页面一个出现java lang NumberFormatEx
  • React-Router V6 使用详解

    一 基本用法 React Router的安装方法 npm npm install react router dom 6 yarn yarn add react router dom 6 目前官方从5开始已经放弃原有的react router