React 第五十二节 Router中 useResolvedPath使用详解和注意事项示例

news2025/6/8 2:27:50

前言

useResolvedPathReact Router v6 提供的一个实用钩子,用于解析给定路径为完整路径对象。
它根据当前路由上下文解析相对路径,生成包含 pathname、search 和 hash 的完整路径对象。

一、useResolvedPath 核心用途

  1. 路径解析:将相对路径解析为绝对路径
  2. 链接构建:安全地构建导航链接
  3. 路径比较:比较当前路径与目标路径
  4. 动态路由处理:正确处理嵌套路由中的路径

二、useResolvedPath 解析结果对象

useResolvedPath 返回一个包含以下属性的对象:
比如原路径是:const resolved = useResolvedPath('../users?id=123#profile')

// 返回内容为
{ pathname: '/users', search: '?id=123', hash: '#profile' }
  1. pathname: 解析后的绝对路径
  2. search: 查询字符串(如果有)
  3. hash: 哈希值(如果有)

三、useResolvedPath 基本用法示例

import { useResolvedPath } from 'react-router-dom';

function PathInfo() {
  const resolved = useResolvedPath('../users?sort=name#section');
  
  return (
    <div>
      <h3>路径解析结果</h3>
      <p>原始路径: "../users?sort=name#section"</p>
      <p>解析后路径名: {resolved.pathname}</p>
      <p>查询参数: {resolved.search}</p>
      <p>哈希值: {resolved.hash}</p>
    </div>
  );
}

四、useResolvedPath 实际应用场景

4.1、在面包屑导航中解析路径

import { useResolvedPath, Link, useLocation, useMatches } from 'react-router-dom';

function Breadcrumbs() {
  const location = useLocation();
  const matches = useMatches();
  
  // 获取所有路由匹配项
  const crumbs = matches
    .filter(match => match.handle?.crumb)
    .map(match => {
      // 解析每个路由的路径
      const resolvedPath = useResolvedPath(match.pathname);
      return {
        pathname: resolvedPath.pathname,
        crumb: match.handle.crumb
      };
    });

  return (
    <nav className="breadcrumbs">
      {crumbs.map((crumb, index) => (
        <span key={index}>
          {index > 0 && ' > '}
          {index === crumbs.length - 1 ? (
            <span className="current">{crumb.crumb}</span>
          ) : (
            <Link to={crumb.pathname}>{crumb.crumb}</Link>
          )}
        </span>
      ))}
    </nav>
  );
}

// 在路由配置中使用
const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      {
        path: 'dashboard',
        handle: { crumb: '控制面板' },
        element: <Dashboard />,
        children: [
          {
            path: 'stats',
            handle: { crumb: '统计' },
            element: <StatsPage />
          }
        ]
      },
      {
        path: 'users',
        handle: { crumb: '用户管理' },
        element: <UsersPage />
      }
    ]
  }
]);

4.2、创建自定义导航链接组件

import { 
  useResolvedPath, 
  useMatch, 
  Link 
} from 'react-router-dom';

function CustomNavLink({ to, children, ...props }) {
  const resolved = useResolvedPath(to);
  const match = useMatch({ path: resolved.pathname, end: true });
  
  return (
    <div className={`nav-item ${match ? 'active' : ''}`}>
      <Link to={to} {...props}>
        {children}
      </Link>
    </div>
  );
}

// 在导航中使用
function Navigation() {
  return (
    <nav>
      <CustomNavLink to="/">首页</CustomNavLink>
      <CustomNavLink to="/about">关于</CustomNavLink>
      <CustomNavLink to="/products">产品</CustomNavLink>
      <CustomNavLink to="/contact">联系我们</CustomNavLink>
    </nav>
  );
}

4.3、在嵌套路由中正确处理相对路径

import { useResolvedPath, Link, Outlet } from 'react-router-dom';

function UserProfileLayout() {
  return (
    <div className="user-profile">
      <nav className="profile-nav">
        <ProfileNavLink to=".">概览</ProfileNavLink>
        <ProfileNavLink to="activity">活动</ProfileNavLink>
        <ProfileNavLink to="settings">设置</ProfileNavLink>
        <ProfileNavLink to="../friends">好友</ProfileNavLink>
      </nav>
      <div className="profile-content">
        <Outlet />
      </div>
    </div>
  );
}

function ProfileNavLink({ to, children }) {
  const resolved = useResolvedPath(to);
  const match = useMatch({ path: resolved.pathname, end: true });
  
  return (
    <Link 
      to={to} 
      className={match ? 'active' : ''}
    >
      {children}
    </Link>
  );
}

// 路由配置
const router = createBrowserRouter([
  {
    path: 'users',
    element: <UsersLayout />,
    children: [
      {
        path: ':userId',
        element: <UserProfileLayout />,
        children: [
          { index: true, element: <ProfileOverview /> },
          { path: 'activity', element: <ProfileActivity /> },
          { path: 'settings', element: <ProfileSettings /> }
        ]
      },
      {
        path: ':userId/friends',
        element: <UserFriends />
      }
    ]
  }
]);

4.4、动态生成侧边栏菜单

import { useResolvedPath, useMatch, Link } from 'react-router-dom';

function SidebarMenu({ items }) {
  return (
    <nav className="sidebar">
      <ul>
        {items.map((item) => (
          <MenuItem key={item.path} to={item.path} label={item.label} />
        ))}
      </ul>
    </nav>
  );
}

function MenuItem({ to, label }) {
  const resolved = useResolvedPath(to);
  const match = useMatch({ path: resolved.pathname, end: false });
  
  return (
    <li className={match ? 'active' : ''}>
      <Link to={to}>{label}</Link>
      
      {/* 显示子菜单(如果存在且匹配) */}
      {match && resolved.pathname === to && (
        <ul className="submenu">
          <li><Link to={`${to}/details`}>详细信息</Link></li>
          <li><Link to={`${to}/analytics`}>分析</Link></li>
        </ul>
      )}
    </li>
  );
}

// 使用示例
const menuItems = [
  { path: '/dashboard', label: '仪表盘' },
  { path: '/projects', label: '项目' },
  { path: '/reports', label: '报告' },
  { path: '/team', label: '团队' }
];

function AppLayout() {
  return (
    <div className="app-layout">
      <SidebarMenu items={menuItems} />
      <main className="content">
        {/* 页面内容 */}
      </main>
    </div>
  );
}

五、useResolvedPath 高级用法:路径比较工具

import { useResolvedPath, useLocation } from 'react-router-dom';

// 自定义钩子:比较当前路径是否匹配目标路径
function usePathMatch(to) {
  const resolvedTo = useResolvedPath(to);
  const location = useLocation();
  
  // 创建当前路径对象(去除可能的尾部斜杠)
  const currentPath = {
    pathname: location.pathname.replace(/\/$/, ''),
    search: location.search,
    hash: location.hash
  };
  
  // 创建目标路径对象
  const targetPath = {
    pathname: resolvedTo.pathname.replace(/\/$/, ''),
    search: resolvedTo.search,
    hash: resolvedTo.hash
  };
  
  // 比较路径是否匹配
  return (
    currentPath.pathname === targetPath.pathname &&
    currentPath.search === targetPath.search &&
    currentPath.hash === targetPath.hash
  );
}

// 在组件中使用
function NavigationItem({ to, children }) {
  const isActive = usePathMatch(to);
  
  return (
    <li className={isActive ? 'active' : ''}>
      <Link to={to}>{children}</Link>
    </li>
  );
}

六、 useResolvedPath 注意事项

6.1、相对路径解析

useResolvedPath 基于当前路由位置解析相对路径

6.2、查询参数和哈希

保留原始路径中的查询字符串和哈希值

6.3、动态路由参数

不会解析路径参数(如 :id),保持原样

6.4、性能考虑

解析操作轻量,但避免在循环中过度使用

6.5、路由上下文

必须在路由组件内部使用(在 <Router> 上下文中)

七、useResolvedPath 与相关钩子对比

在这里插入图片描述

总结

useResolvedPathReact Router v6 中处理路径的强大工具,主要用于:

  1. 在嵌套路由中正确处理相对路径
  2. 构建动态导航组件
  3. 创建面包屑导航等复杂导航结构
  4. 安全地比较路径和构建链接

通过合理使用 useResolvedPath,可以创建更健壮、可维护的路由结构,避免硬编码路径导致的错误,并简化嵌套路由中的路径处理逻辑。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cursor快速梳理ipynb文件Prompt

1. 整体鸟瞰 请在不运行代码的前提下&#xff0c;总结 <文件名.ipynb> 的主要目的、核心逻辑流程和输出结果。阅读整个项目目录&#xff0c;列出每个 .ipynb / .py 文件的角色&#xff0c;以及它们之间的数据依赖关系&#xff08;输入→处理→输出&#xff09;。2. 结构…

天机学堂-分页查询

需求 分页查询我的课表 返回&#xff1a; 总条数、总页数、当前页的课表信息的集合 返回的VO&#xff08;已经封装成统一的LearningLessonsVO&#xff09; 定义Controller RestController RequestMapping("/lessons") RequiredArgsConstructor public class Lear…

微算法科技(NASDAQ:MLGO)基于信任的集成共识和灰狼优化(GWO)算法,搭建高信任水平的区块链网络

随着数字化转型的加速&#xff0c;区块链技术作为去中心化、透明且不可篡改的数据存储与交换平台&#xff0c;正逐步渗透到金融、供应链管理、物联网等多个领域&#xff0c;探索基于信任的集成共识机制&#xff0c;并结合先进的优化算法来提升区块链网络的信任水平&#xff0c;…

全新Xsens Animate版本是迄今为止最大的软件升级,提供更清晰的数据、快捷的工作流程以及从录制开始就更直观的体验

我们整合了专业人士喜爱的 Xsens 动捕功能&#xff0c;并使其更加完善。全新Xsens Animate版本是我们迄今为止最大的软件升级&#xff0c;旨在提供更清晰的数据、更快捷的工作流程以及从录制开始就更直观的体验。 从制作游戏动画到流媒体直播头像或构建实时电影内容&#xff0…

大语言模型评测体系全解析(下篇):工具链、学术前沿与实战策略

文章目录 一、评测工具链&#xff1a;从手工测试到自动化工程的效率革命&#xff08;一&#xff09;OpenCompass&#xff1a;开源评测框架的生态构建1. 技术架构&#xff1a;三层架构实现评测自动化2. 开发者赋能&#xff1a;从入门到进阶的工具矩阵 &#xff08;二&#xff09…

python打卡day46@浙大疏锦行

知识点回顾&#xff1a; 不同CNN层的特征图&#xff1a;不同通道的特征图什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。通道注意力&#xff1a;模型的定义和插入的位置通道注意力后的特征图和热力图 内…

Excel 发现此工作表中有一处或多处公式引用错误。请检查公式中的单元格引用、区域名称、已定义名称以及到其他工作簿的链接是否均正确无误。弹窗

Excel 提示“发现此工作表中有一处或多处公式引用错误”通常表示公式中存在无效引用。以下是系统化的检查步骤&#xff0c;帮助你定位和修复问题&#xff1a; 1. 检查单元格引用&#xff1a; 无效单元格引用&#xff1a;检查公式中的单元格地址&#xff08;如 A1、B10&…

NVIDIA DRIVE AGX平台:引领智能驾驶安全新时代

随着科技的不断进步&#xff0c;汽车行业正迎来前所未有的变革&#xff0c;智能驾驶技术成为全球产业竞相布局的焦点之一。然而&#xff0c;这场技术革命的背后&#xff0c;最关键且被广泛关注的是安全性问题。近日&#xff0c;我认真研读了NVIDIA发布的《自动驾驶安全报告》白…

推荐12个wordpress企业网站模板

WordPress企业网站模板是一种专为企业网站设计的WordPress主题&#xff0c;旨在帮助企业创建专业、美观且易于管理的网站。这些模板通常具备响应式设计、SEO优化、多语言支持等功能&#xff0c;能够满足不同行业和企业的需求。 WordPress企业网站模板的适用场景 企业官网&…

沙市区举办资本市场赋能培训会 点赋科技分享智能消费新实践

荆州市沙市区&#xff0c;2025年6月5日—— 在沙市区政府主办的“发挥区域性股权市场功能&#xff0c;助力企业拥抱资本市场”专题培训会上&#xff0c;区委副书记、区长郭熙胜强调要充分发挥资本市场服务实体经济功能&#xff0c;推动本土创新企业高质量发展。区内重点企业点赋…

探秘鸿蒙 HarmonyOS NEXT:实战用 CodeGenie 构建鸿蒙应用页面

在开发鸿蒙应用时&#xff0c;你是否也曾为一个页面的布局反复调整&#xff1f;是否还在为查 API、写模板代码而浪费大量时间&#xff1f;今天带大家实战体验一下鸿蒙官方的 AI 编程助手——CodeGenie&#xff08;代码精灵&#xff09; &#xff0c;如何从 0 到 1 快速构建一个…

art-pi2 上手记录(二)

功能比较庞杂&#xff0c;写得不好&#xff0c;抛砖引玉 预备知识 stm32 默认从主闪存0x08000000启动 art-pi2的psram 映射0x90000000 art-pi2的8线ospi flash 映射0x70000000 stm32h7比较灵活&#xff0c;通过修改选项字节&#xff0c;可以实现从 0x0000 0000 到 0x3FFF 0…

数据库SQLite基础

SQLite的存储结构 --->B树 大型数据库 &#xff1a;Oracle 中型数据库 &#xff1a;Server是微软开发的数据库产品&#xff0c;主要支持windows平台 小型数据库 : MySQL是一个小型关系型数据库管理系统。开放源码 (嵌入式不需要存储太多数据) 一、SQLite基础 SQLite的源代码…

1.3 古典概型和几何概型

文章目录 古典概型模型(等可能模型)几何概型 古典概型模型(等可能模型) 两个条件&#xff1a; 1) 有限个样本点 2) 等可能性 例题&#xff1a; 设有n个人&#xff0c;每个人都等可能地被分配到N个房间中的任一间(n≤N)&#xff0c; 求下列事件的概率: (1)某指定的n间房…

html-pre标签

我们都知道在常见标签里面的文字的格式是不会显示的&#xff0c;比如你打了多个空格&#xff0c;但却不会显示&#xff0c;而pre标签会显示。 主要特点&#xff1a; 保留空格和换行&#xff1a;在 <pre> 标签内&#xff0c;HTML 会保留所有的空格、换行符和制表符等格式…

【WPF】WPF 项目实战:用ObservableCollection构建一个可增删、排序的管理界面(含源码)

&#x1f4a1;WPF 项目实战&#xff1a;构建一个可增删、排序的光源类型管理界面&#xff08;含源码&#xff09; 在实际的图像处理项目中&#xff0c;我们经常需要对“光源类型”进行筛选或管理。今天我们来一步步构建一个实用的 WPF 界面&#xff0c;实现以下功能&#xff1…

MCU_IO驱动LED

注意事项&#xff1a; 1、亮度要求较高的情况下&#xff0c;不能由IO直接驱动LED MCU_IO引脚输出的电压和电流较弱&#xff0c;如果对光的亮度有要求的话&#xff0c;需要使用三极管来驱动。 MCU_IO的电压一般为3.3V或者5V&#xff0c;输出电流一般10mA-25mA。 2、不同颜色…

上门预约行业技术方案全解析:小程序、App还是H5?如何选择?

上门按摩行业这几年确实火&#xff0c;但千万别以为随便买个系统、招几个技师就能赚钱。作为一家深耕10年软件开发的公司&#xff0c;我们做了四五年上门按摩系统&#xff0c;见过太多人头脑一热冲进来&#xff0c;结果血本无归。 如果你真的想做上门按摩&#xff0c;先想清楚这…

Java 大视界 -- 基于 Java 的大数据分布式计算在蛋白质组学数据分析中的加速与优化(255)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

Vue.js教学第十八章:Vue 与后端交互(二):Axios 拦截器与高级应用

Vue 与后端交互(二):Axios 拦截器与高级应用 在上一篇文章中,我们学习了 Axios 的基本用法,包括如何发送不同类型的 HTTP 请求以及基本的配置选项。本文将深入剖析 Axios 的拦截器功能,探讨请求拦截器和响应拦截器的作用、配置方法和应用场景,通过实例展示如何利用拦截…