HOW - React Router v6.x Feature 实践(react-router-dom)

目录

  • 基本特性
  • ranked routes matching
  • active links
    • NavLink
    • useMatch
  • relative links
      • 1. 相对路径的使用
      • 2. 嵌套路由的增强行为
      • 3. 优势和注意事项
      • 4. . 和 ..
      • 5. 总结
  • data loading
  • loading or changing data and redirect
  • pending navigation ui
  • skeleton ui with suspense
  • data mutations with `<Route action>`
  • busy indicators with route actions
  • data fetchers

基本特性

  1. client side routing
  2. nested routes
  3. dynamic segments

比较好理解,这里不赘述。

ranked routes matching

https://reactrouter.com/en/main/start/overview#ranked-route-matching

When matching URLs to routes, React Router will rank the routes according to the number of segments, static segments, dynamic segments, splats, etc. and pick the most specific match.

这句话描述了 React Router 在匹配 URL 和路由时的策略,即根据路由的具体性来优先选择最合适的匹配项。让我们逐步解析这句话的含义:

  1. URL 和路由的匹配

    • 当用户访问某个 URL 时,React Router 需要确定哪个路由规则最适合处理该 URL。例如,对于 URL /users/123,React Router 需要决定是匹配 /users/:id 还是其他定义的路由。
  2. 路由匹配的考量因素:优先级由高到低

    • 路由的段数(Segments):URL 和路由可以分成多个段(segments),例如 /users/123 有两个段,/users/:id 也有两个段。React Router 会比较 URL 和每个路由的段数,越多的段数一般意味着路由更具体。

    • 静态段(Static Segments):静态段是指在路由中直接指定的固定路径,例如 /users 是一个静态段。React Router 会考虑静态段的数量来确定路由的具体性。

    • 动态段(Dynamic Segments):动态段是指在路由中使用参数化路径,例如 /users/:id 中的 :id 是一个动态段。动态段的存在可能使得路由更灵活但也更具体。

    • 通配符(Splat):通配符(如 *)表示匹配多个路径段,通常用于处理不确定数量的路径部分。

  3. 最具体的匹配

    • React Router 会通过比较以上因素来确定哪个路由定义是最具体的匹配。具体的路由定义意味着它能够最准确地匹配当前的 URL,而不会与其他可能的路由定义冲突。
  4. 示例

<Route path="/teams/:teamId" />
<Route path="/teams/new" />

对于 http://example.com/teams/new. 会优先匹配第二个 Route。因为静态段数为 2,更具体。

理解 React Router 的路由匹配策略,特别是根据路由的具体性来优先选择最合适的匹配项,有助于开发者更有效地设计和管理复杂的路由结构。通过正确的路由定义和优先级排序,可以确保应用程序在导航和页面渲染时行为符合预期,并能够灵活地应对各种场景和URL路径。

active links

NavLink

https://reactrouter.com/en/main/components/nav-link

<NavLink
  style={({ isActive, isPending }) => {
    return {
      color: isActive ? "red" : "inherit",
    };
  }}
  className={({ isActive, isPending }) => {
    return isActive ? "active" : isPending ? "pending" : "";
  }}
/>

useMatch

https://reactrouter.com/en/main/hooks/use-match

function SomeComp() {
  const match = useMatch("/messages");
  return <li className={Boolean(match) ? "active" : ""} />;
}

relative links

理解 React Router 中 <Link><NavLink> 组件相对路径的使用需要考虑它们与 HTML 中 <a> 标签的行为差异,尤其是在嵌套路由场景下的增强行为。

1. 相对路径的使用

  • HTML <a> 标签:在 HTML 中,使用 <a> 标签时,相对路径通常相对于当前页面的完整 URL。这意味着,相对路径会根据当前页面的路径来构建最终的目标 URL。

    <a href="about">About</a>
    
    • 如果当前 URL 是 http://example.com/home,那么点击上述链接将导航到 http://example.com/about
  • React Router 中的 <Link><NavLink>:在 React Router 中,<Link><NavLink> 组件可以接受相对路径,但它们的行为略有不同。

    import { Link, NavLink } from 'react-router-dom';
    
    <Link to="about">About</Link>
    <NavLink to="about">About</NavLink>
    
    • 这里的 to="about" 是相对路径,相对于当前路由的路径来构建目标 URL。例如,如果当前路由是 /home,那么这两个链接将会导航到 /home/about

2. 嵌套路由的增强行为

  • 嵌套路由:当应用程序中存在嵌套路由时,React Router 的 <Link><NavLink> 组件表现出更智能的行为,确保相对路径的正确解析。

    <Route path="/home">
      <Link to="about">About</Link>
      <NavLink to="about">About</NavLink>
    </Route>
    
    • 在上述例子中,假设当前路由是 /home,那么 <Link><NavLink> 组件会基于当前路由的路径 /home 构建相对路径,导航到 /home/about

3. 优势和注意事项

  • 灵活性和便利性:相对路径的使用使得在应用中链接管理更加灵活和简单,尤其是在处理嵌套路由时。

  • 注意路径解析:确保理解相对路径在不同嵌套层级下的解析规则。React Router 的行为通常是基于当前活动的路由来解析相对路径,而不是简单地相对于根路径

4. . 和 …

<Route path="/home">
  <Link to=".">About</Link>
  <NavLink to=".">About</NavLink>
</Route>
  • 在上述例子中,假设当前路由是 /home,那么 <Link><NavLink> 组件会基于当前路由的路径 /home 构建相对路径,导航到 /home
<Route path="home" element={<Home />}>
  <Route path="project/:projectId" element={<Project />}>
  	<Route path=":taskId" element={<Task />} />
  </Route>
</Route>

Project 中会渲染:

  <Link to="abc">
  <Link to=".">
  <Link to=".."></Link>
  <Link to=".." relative="path">
  • 在上述例子中,假设当前路由是 /home/project/123,那么 <Link> 会基于当前路由的路径构建相对路径,分别导航到 /home/project/123/abc/home/project/abc/home/home/project

注意后面两个的差异:

By default, the … in relative links traverse the route hierarchy, not the URL segments. Adding relative=“path” in the next example allows you to traverse the path segments instead.

5. 总结

理解 React Router 中 <Link><NavLink> 组件相对路径的行为,特别是在嵌套路由情况下的增强行为,有助于开发者更有效地管理和导航应用程序中的链接。相对路径的使用使得在不同层级和场景下的导航操作更加灵活和便捷,但需要注意理解和控制路径的解析和构建规则。

data loading

https://reactrouter.com/en/main/start/overview#data-loading

Combined with nested routes, all of the data for multiple layouts at a specific URL can be loaded in parallel.

<Route
  path="/"
  loader={async ({ request }) => {
    // loaders can be async functions
    const res = await fetch("/api/user.json", {
      signal: request.signal,
    });
    const user = await res.json();
    return user;
  }}
  element={<Root />}
>
  <Route
    path=":teamId"
    // loaders understand Fetch Responses and will automatically
    // unwrap the res.json(), so you can simply return a fetch
    loader={({ params }) => {
      return fetch(`/api/teams/${params.teamId}`);
    }}
    element={<Team />}
  >
    <Route
      path=":gameId"
      loader={({ params }) => {
        // of course you can use any data store
        return fakeSdk.getTeam(params.gameId);
      }}
      element={<Game />}
    />
  </Route>
</Route>

Data is made available to your components through useLoaderData.

function Root() {
  const user = useLoaderData();
  // data from <Route path="/">
}

function Team() {
  const team = useLoaderData();
  // data from <Route path=":teamId">
}

function Game() {
  const game = useLoaderData();
  // data from <Route path=":gameId">
}

When the user visits or clicks links to https://example.com/real-salt-lake/45face3, all three route loaders will be called and loaded in parallel, before the UI for that URL renders.

loading or changing data and redirect

https://reactrouter.com/en/main/route/loader#throwing-in-loaders

<Route
  path="dashboard"
  loader={async () => {
    const user = await fake.getUser();
    if (!user) {
      // if you know you can't render the route, you can
      // throw a redirect to stop executing code here,
      // sending the user to a new route
      throw redirect("/login");
    }

    // otherwise continue
    const stats = await fake.getDashboardStats();
    return { user, stats };
  }}
/>

pending navigation ui

https://reactrouter.com/en/main/start/overview#pending-navigation-ui

When users navigate around the app, the data for the next page is loaded before the page is rendered. It’s important to provide user feedback during this time so the app doesn’t feel like it’s unresponsive.

function Root() {
  const navigation = useNavigation();
  return (
    <div>
      {navigation.state === "loading" && <GlobalSpinner />}
      <FakeSidebar />
      <Outlet />
      <FakeFooter />
    </div>
  );
}

skeleton ui with suspense

https://reactrouter.com/en/main/start/overview#skeleton-ui-with-suspense

Instead of waiting for the data for the next page, you can defer data so the UI flips over to the next screen with placeholder UI immediately while the data loads.

defer enables suspense for the un-awaited promises

<Route
  path="issue/:issueId"
  element={<Issue />}
  loader={async ({ params }) => {
    // these are promises, but *not* awaited
    const comments = fake.getIssueComments(params.issueId);
    const history = fake.getIssueHistory(params.issueId);
    // the issue, however, *is* awaited
    const issue = await fake.getIssue(params.issueId);

    // defer enables suspense for the un-awaited promises
    return defer({ issue, comments, history });
  }}
/>;

function Issue() {
  const { issue, history, comments } = useLoaderData();
  return (
    <div>
      <IssueDescription issue={issue} />

      {/* Suspense provides the placeholder fallback */}
      <Suspense fallback={<IssueHistorySkeleton />}>
        {/* Await manages the deferred data (promise) */}
        <Await resolve={history}>
          {/* this calls back when the data is resolved */}
          {(resolvedHistory) => (
            <IssueHistory history={resolvedHistory} />
          )}
        </Await>
      </Suspense>

      <Suspense fallback={<IssueCommentsSkeleton />}>
        <Await resolve={comments}>
          {/* ... or you can use hooks to access the data */}
          <IssueComments />
        </Await>
      </Suspense>
    </div>
  );
}

function IssueComments() {
  const comments = useAsyncValue();
  return <div>{/* ... */}</div>;
}

涉及如下 API 结合使用:

  1. defer
  2. Await
  3. useAsyncValue

data mutations with <Route action>

https://reactrouter.com/en/main/start/overview#data-mutations

HTML forms are navigation events, just like links. React Router supports HTML form workflows with client side routing.

When a form is submitted, the normal browser navigation event is prevented and a Request, with a body containing the FormData of the submission, is created. This request is sent to the <Route action> that matches the form’s <Form action>.

Form elements’s name prop are submitted to the action:

<Form action="/project/new">
  <label>
    Project title
    <br />
    <input type="text" name="title" />
  </label>

  <label>
    Target Finish Date
    <br />
    <input type="date" name="due" />
  </label>
</Form>
<Route
  path="project/new"
  action={async ({ request }) => {
    const formData = await request.formData();
    const newProject = await createProject({
      title: formData.get("title"),
      due: formData.get("due"),
    });
    return redirect(`/projects/${newProject.id}`);
  }}
/>

在 HTML 中,<form> 元素的 action 属性定义了当用户提交表单时将数据发送到的服务器端的 URL。

具体来说:

  • action 属性的作用

    • 当用户提交表单时,浏览器会将表单中的数据发送到指定的 URL。
    • 这个 URL 可以是相对路径或绝对路径。
    • 如果 action 属性未指定,表单会被提交到当前页面的 URL(即自身)。
  • 使用示例

    <form action="/project/new" method="post">
        <!-- 表单内容 -->
        <input type="text" name="project_name" />
        <button type="submit">提交</button>
    </form>
    
    • 在这个例子中,action 属性的值是 "/project/new"。当用户点击提交按钮时,表单数据将被发送到当前服务器的 /project/new 路径。
  • 重要说明

    • 如果 action 属性指向一个相对路径,表单数据会被提交到当前页面的基础 URL 加上 action 的值。
    • 如果 action 属性是绝对路径(例如 http://example.com/project/new),数据将被发送到指定的绝对路径。
  • HTTP 方法 (method 属性)

    • 另一个与 action 相关的重要属性是 method,它指定了使用何种 HTTP 方法将表单数据发送到服务器。
    • 常见的方法是 GETPOSTGET 方法将数据附加到 URL 上(可见),而 POST 方法将数据包含在请求体中(不可见)。

总结来说,action 属性定义了表单数据提交的目标 URL。这对于将用户输入数据发送到后端处理或其他指定的处理程序非常重要。

busy indicators with route actions

https://reactrouter.com/en/main/start/overview#busy-indicators

When forms are being submitted to route actions, you have access to the navigation state to display busy indicators, disable fieldsets, etc.

function NewProjectForm() {
  const navigation = useNavigation();
  const busy = navigation.state === "submitting";
  return (
    <Form action="/project/new">
      <fieldset disabled={busy}>
        <label>
          Project title
          <br />
          <input type="text" name="title" />
        </label>

        <label>
          Target Finish Date
          <br />
          <input type="date" name="due" />
        </label>
      </fieldset>
      <button type="submit" disabled={busy}>
        {busy ? "Creating..." : "Create"}
      </button>
    </Form>
  );
}

data fetchers

HTML Forms are the model for mutations but they have one major limitation: you can have only one at a time because a form submission is a navigation.

Most web apps need to allow for multiple mutations to be happening at the same time, like a list of records where each can be independently deleted, marked complete, liked, etc.

Fetchers allow you to interact with the route actions and loaders without causing a navigation in the browser, but still getting all the conventional benefits like error handling, revalidation, interruption handling, and race condition handling.

Imagine a list of tasks:

function Tasks() {
  const tasks = useLoaderData();
  return tasks.map((task) => (
    <div>
      <p>{task.name}</p>
      <ToggleCompleteButton task={task} />
    </div>
  ));
}

Each task can be marked complete independently of the rest, with its own pending state and without causing a navigation with a fetcher:

function ToggleCompleteButton({ task }) {
  const fetcher = useFetcher();

  return (
    <fetcher.Form method="post" action="/toggle-complete">
      <fieldset disabled={fetcher.state !== "idle"}>
        <input type="hidden" name="id" value={task.id} />
        <input
          type="hidden"
          name="status"
          value={task.complete ? "incomplete" : "complete"}
        />
        <button type="submit">
          {task.status === "complete"
            ? "Mark Incomplete"
            : "Mark Complete"}
        </button>
      </fieldset>
    </fetcher.Form>
  );
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/783418.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(三)前端javascript中的数据结构之链表上

在js中&#xff0c;没有为我们提供原生的数据结构支持的&#xff0c;但是在java中是有提供的。所以需要我们去模拟这种结构实现。 链表中最关键的一个元素&#xff0c;就是头节点&#xff0c;头节点不存储数据&#xff0c;指向第一个节点链表中几乎所有的操作都要从头结点开始。…

数字流的秩

题目链接 数字流的秩 题目描述 注意点 x < 50000 解答思路 可以使用二叉搜索树存储出现的次数以及数字的出现次数&#xff0c;方便后续统计数字x的秩关键在于构建树的过程&#xff0c;如果树中已经有值为x的节点&#xff0c;需要将该节点对应的数字出现次数加1&#xf…

味全财税数字化实践分享,百望云助力实现数电票管理能力升级!

随着金税四期的启动&#xff0c;数电票全面落地应用&#xff0c;这不仅大幅提高了发票处理效率&#xff0c;更重塑了企业的财务管理流程&#xff0c;为企业财务数字化转型指明了新的方向。 杭州味全食品有限公司&#xff08;以下简称“味全”&#xff09;正在推进财税数字化建设…

(2024,稀疏 MoE,大量小专家,参数高效专家检索 PEER,product key 检索)混合百万专家

Mixture of A Million Experts 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 2. 方法 3. 实验 0. 摘要 标准 Transformer 架构中的前馈&#xff08;feedforward&a…

轻松集成,高效变现:Flat Ads SDK助力开发者轻松跨越广告变现门槛

在当今的移动应用开发领域,广告变现是开发者们普遍关注的重要话题。如何在不影响用户体验的前提下,最大化地实现广告收益,成为了许多开发者面临的挑战。为此,Flat Ads SDK 应运而生,它以“轻松集成,合规守护,高效变现”为核心理念,帮助开发者轻松解决流量变现难题。 一、高效变…

tauri + vue3 如何实现在一个页面上局部加载外部网页?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

惟客数据Q2荣誉成绩单新鲜出炉

作为众多头部企业客户的数字化经营合作伙伴 WakeData惟客数据一直坚持以客户为中心&#xff0c;以数据驱动 致力于让数据智能商业落地更敏捷 凭借值得信赖的客户经营数字化和资源管理数字化实力 惟客数据在2024年第二季度斩获多项荣誉 1、 第一新声《2023年度中国高科技高…

从入门到精通:Shopee,lazada,temu自养号测评成本、步骤、技巧详解

测评对于卖家来说是一种成本低回报快的推广方式&#xff0c;可以减少高额的平台广告费用&#xff0c;因此是一种很好的辅助手段&#xff0c;对商品的曝光、流量、转化和权重等方面起到了很好的辅助作用 建议还是自己精养一批账号&#xff0c;账号在自己手里比较安全可控&#…

python中getattr/setattr/hasattr/delattr函数都是干什么的?

目录 1、getattr&#xff1a;动态获取属性 &#x1f50d; 1.1 动态获取属性 1.2 默认值处理技巧 1.3 实战案例&#xff1a;配置文件动态加载 2、setattr&#xff1a;动态设置属性 &#x1f6e0; 2.1 修改对象属性 2.2 新增属性场景 2.3 应用场景&#xff1a;类的动态配置…

Linux 命令历史、补全和正则表达式

1.命令历史就和windows的ctrlz一个概念&#xff0c;就是返回上一次的命令。 按下小键盘上下切换 ctrlc可以终止本次输入&#xff0c;进行下一次输入。 2.tab键可以自动补全&#xff08;有点鸡肋&#xff09; 3.正则表达式 类似于word的快速搜索&#xff0c;Linux也是用*和…

浅析C++引用

浅析C引用"&" ​ C中引入了一个新的语言特性——引用(&)&#xff0c;它表示某一对象的别名&#xff0c;对象与该对象的引用都是指向统一地址。那么我们就来看看关于引用的一些知识点吧&#x1f9d0; 特性 引用在定义时必须初始化一个变量可以有多个引用引…

zdppy_api+vue3+antd前后端分离开发,使用描述列表组件渲染用户详情信息

后端代码 import api import upload import time import amcomment import env import mcrud import amuserdetailsave_dir "uploads" env.load(".env") db mcrud.new_env()app api.Api(routes[*amcomment.get_routes(db),*amuserdetail.get_routes(db…

记一次微信小程序逆向

扫码领取网安教程 遇到瓶颈了&#xff0c;不知道该干什么&#xff0c;突然想到学校的小程序 闲来无事就看一看 抓包下来的数据是这样的&#xff0c;嗯&#xff0c;下机&#xff08;hhh 一、反编译程序 加密嘛&#xff0c;之前抓了看到是加密就放弃了&#xff0c;现在重新弄一…

轻松转换!两款AI工具让word秒变ppt!

想把Word文档一键生成PPT&#xff0c;过去有一个很常见的做法&#xff1a;先在Word文档中设置标题样式&#xff0c;通过标题样式来分隔每一部分&#xff0c;之后导出为PPT&#xff0c;就能得到一份PPT的雏形&#xff0c;但这种方法无法对PPT自动进行美化&#xff0c;即得到的只…

js替换对象内部的对象名称或属性名称-(第二篇)递归

1.代码示例&#xff1a; function replaceKey(obj, oldKey, newKey) {// 如果不是对象或者oldKey不存在&#xff0c;直接返回原对象if (typeof obj ! object || !obj || !(oldKey in obj)) return obj;// 如果是数组&#xff0c;遍历数组每个元素if (Array.isArray(obj)) {obj…

【Python】一文向您详细介绍 np.inner()

【Python】一文向您详细介绍 np.inner() 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&#xff0c;曾…

君方智能设计平台-对象持久化技术方案

1.背景介绍 1.1序列化功能 序列化是将复杂的图形对象、数据结构或对象转换成一种可被存储、传输或分享的格式的过程。这个格式通常是二进制或文本形式&#xff0c;能够轻松地保存在文件中或通过网络发送到其他应用程序。序列化的目的是将数据持久化&#xff0c;使其在不同时间…

【学术会议征稿】2024年第四届工商管理与数据科学学术会议(BADS 2024)

2024年第四届工商管理与数据科学学术会议(BADS 2024) 2024 4th International Conference on Business Administration and Data Science 2024年第四届工商管理与数据科学学术会议(BADS 2024)将于2024年10月25-27日在新疆喀什召开&#xff0c;由喀什大学支持本次会议。会议旨…

Mapboxgl 根据 AWS 地形的高程值制作等高线

更多精彩内容尽在dt.sim3d.cn&#xff0c;关注公众号【sky的数孪技术】&#xff0c;技术交流、源码下载请添加VX&#xff1a;digital_twin123 使用mapboxgl 3.0版本&#xff0c;根据 AWS 地形图块的高程值制作等高线&#xff0c;源码如下&#xff1a; <!DOCTYPE html> &…

OV证书签发一般要多久?

OV证书&#xff0c;即组织验证型SSL证书&#xff0c;的签发流程涉及多个阶段&#xff0c;其具体时间取决于多种因素。OV证书的签发一般需要1-3个工作日&#xff0c;这个过程可以分为以下几个阶段&#xff1a; 1、选择和购买证书&#xff1a; 用户需要在SSL证书服务商处选择合适…