useRoute
useRoute 是对 React Router 的一个自定义封装,用于获取当前路由的相关信息并进行处理与扩展。它除了返回最后一个匹配的路由的常规属性,还包含对查询参数 (query)、散列值 (hash)、完整路径 (fullPath)、错误信息 (error) 等的便捷获取,同时对动态路由参数 (params) 进行了特殊处理(如 [...slug] 转换成字符串数组)。
函数签名
export function useRoute<
T = unknown,
Q extends Record<string, string> | null = Record<string, string>,
P extends Record<string, string | string[]> = Record<string, string | string[]>
>(): Router.Route<T, Q, P>泛型参数
T: 路由数据类型 代表当前路由在loader/clientLoader中返回的 data 类型。默认为unknown。Q: 查询参数类型 解析自location.search的查询参数对象类型,默认为Record<string, string>(也可为null)。P: 路径参数类型 在动态路由匹配(如:id或[...slug])时解析到的params类型,默认为Record<string, string | string[]>。- 对于
[...slug]之类的路由,会将params.slug转换为 字符串数组; - 对于普通的
:id,则是单一字符串。
- 对于
返回值
该 Hook 返回一个扩展后的路由对象,类型为 Router.Route<T, Q, P>,包含以下主要字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| data | T | 通过路由 loader / clientLoader 返回的结果。 |
| handle | RouteHandle | 路由模块中自行定义并导出的 handle 对象。 |
| error | Error | null | 当前路由处理或渲染过程中抛出的错误对象,如果无错误则为 null。 |
| fullPath | string | 当前完整的 URL 路径,包含 pathname + search + hash。 |
| hash | string | location.hash 的值(如 #section-1)。 |
| matched | UIMatch<T, RouteHandle>[] | 已匹配到的所有路由对象集合(大多情况下,第 0 个为根布局,业务路由从第 1 项开始)。 |
| params | P (默认为 Record<string, string | string[]>) | 动态路径参数,特殊情况如 [...slug] 会被解析为字符串数组。 |
| pathname | string | location.pathname(如 /blog/123)。 |
| query | Q (默认为 Record<string, string> | null) | 解析自 location.search 的查询参数对象(如 ?page=1 解析为 { page: '1' })。 |
| search | string | location.search(如 ?page=1)。 |
提示:
data即路由loader/clientLoader函数返回的值(或者是通过其他方式挂载到路由的异步数据)。handle是在定义路由时,自行在路由模块中导出的对象,可用于存放自定义的元信息、函数等。
核心逻辑说明
- 路由匹配与取值
- 通过 React Router 提供的
useMatches获取当前所有匹配路由,并以matches.at(-1)作为当前活跃路由信息来源。
- 通过 React Router 提供的
- 获取基础信息
- 调用
useLocation()获得hash,pathname,search,拼接成fullPath。
- 调用
- 解析查询参数
- 使用自定义函数(如
parseQuery)将search解析为对象,赋给query。
- 使用自定义函数(如
- 获取错误
- 调用
useRouteError()获得当前路由报错(若有),存入error。
- 调用
- 自定义 params
- 如果路由包含 catch-all 动态参数
[...slug],会将params['*']拆分为字符串数组,如params.slug = ['abc','def']。
- 如果路由包含 catch-all 动态参数
- useMemo 缓存
- 仅在依赖(如
fullPath)变化时,才重新计算并返回路由对象。
- 仅在依赖(如
使用示例
import React from 'react';
import { useRoute } from '@/hooks/useRoute';
// 定义泛型 T = PostData, Q = { page: string }, P = { slug: string[] }
function PostDetail() {
const { data, handle, error, params, query, pathname, fullPath } = useRoute<PostData, { page: string }, { slug: string[] }>();
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
<h2>Post Detail</h2>
<p>Handle: {JSON.stringify(handle)}</p>
<p>Data from loader: {JSON.stringify(data)}</p>
<p>Params: {JSON.stringify(params)}</p>
<p>Query: {JSON.stringify(query)}</p>
<p>Pathname: {pathname}</p>
<p>FullPath: {fullPath}</p>
</div>
);
}
export const loader = async ({ params }: { params: { slug: string[] } }) => {
return {
data: {
slug: params.slug
}
}
}- 如果当前路由为
/post/abc/def?page=2且路由定义为[...slug]:params.slug=>['abc', 'def']query=>{ page: '2' }pathname=>/post/abc/deffullPath=>/post/abc/def?page=2- 如果在路由模块中导出了
handle,可在此处通过handle获取。
通过 useRoute,你可在业务组件中一站式获取到解析后的路由信息,省去频繁在多个 Hook 间切换的麻烦,并自动处理多段参数等特殊场景,让开发更高效、代码更整洁。
Last updated on