在 React 中,我们经常需要获取和处理 URL 中的查询参数。特别是在单页应用(SPA)中,路由参数的管理和转换非常常见。为了提高代码的复用性和可维护性,我们可以使用 React 的 Hook 来封装这类逻辑,确保代码简洁、易于维护。通过实现一个自定义的 useRouterParams Hook 来演示如何获取 URL 中的查询参数,并根据需求进行解析和转换。
背景
在前端开发中,路由查询参数(Query Parameters)是非常常见的。例如,在一个电商平台中,可能会通过 URL 的查询参数来传递过滤条件(如类别、价格区间等)。对于多页面应用(MPA)或单页面应用(SPA),获取和处理这些参数是必不可少的操作。
React 官方提供的 useLocation 和 useHistory 钩子可以帮助我们访问路由,但它们默认只返回完整的 URL 信息,没有直接提供对查询参数的处理。因此,我们需要编写一个自定义 Hook 来简化这个过程。
实现思路
我们希望创建一个 useRouterParams 的 Hook,它具有以下功能:
• 获取当前页面的查询参数。
• 可以选择对查询参数进行转换(例如,转换为数值类型或枚举类型)。
• 提供一种简便的方式来访问和管理查询参数。
代码实现
下面是 useRouterParams Hook 的实现代码:
import { useMemo } from 'react'
export type DefaultParams = Partial<Record<string, string>>
/**
* 获取路由参数。
* 这个钩子允许开发者类型化路由参数,并可选地提供一个解析函数来处理参数。
*
* @param option.parseFn 解析函数。默认路由参数都是string类型。有些时候你需要转换成其他类型(数值/枚举)等。你可以通过传递这个参数来处理参数。
*
*/
export function useRouterParams<T = DefaultParams>(
option: {
transform?: (data: T) => T
} = {}
) {
const url = new URL(window.location.href)
const params = getQueryParams(url?.href) as T
const _param = useMemo(() => {
// 计算key
let cparam: T = params as T
try {
if (option.transform) cparam = option.transform(cparam)
} catch (event) {
// eslint-disable-next-line no-console
console.error('parseFn 执行失败:', event)
}
return { ...params, ...cparam } as T
}, [params])
return [_param as T] as const
}
// 正则表达式提取查询字符串
function getQueryParams(url: string): Record<string, string> {
const queryString = url.split('?')[1] || ''
const params: Record<string, string> = {}
// 匹配所有的 key=value 对
queryString.replace(/([^=&]+)=([^&]*)/g, (_match, key, value) => {
params[decodeURIComponent(key)] = decodeURIComponent(value)
return ''
})
return params
}
简单实例
