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/def
fullPath
=>/post/abc/def?page=2
- 如果在路由模块中导出了
handle
,可在此处通过handle
获取。
通过 useRoute
,你可在业务组件中一站式获取到解析后的路由信息,省去频繁在多个 Hook 间切换的麻烦,并自动处理多段参数等特殊场景,让开发更高效、代码更整洁。
Last updated on