import qs, { IParseOptions, IStringifyOptions } from "qs";
import { useCallback, useMemo, useRef } from "react";
import { NavigateOptions, useLocation, useNavigate } from "react-router-dom";
/**
* 使用 qs 库配合 react router 来处理 url 查询参数
*
* @param def 查询参数的默认值
* @param options qs配置
* @param options.parseOptions qs 解析配置
* @param options.stringifyOptions qs 序列化配置
*/
export default function useQs<T extends qs.ParsedQs>(
def?: T,
options: {
parseOptions?: IParseOptions;
stringifyOptions?: IStringifyOptions;
} = {}
) {
const optionsRef = useRef(options);
const defaultQS = useRef(def);
const location = useLocation();
const navigate = useNavigate();
/** 当前 url 的参数数据,使用 qs 解析 */
const query: T = useMemo(() => {
const queryStr = location.search.slice(1);
const parsed = qs.parse(queryStr, optionsRef.current.parseOptions) as T;
const merged = { ...defaultQS.current, ...parsed };
return merged;
}, [location.search]);
/**
* 一个用于路由的函数,传入任意对象,使用 qs 压缩字符串后,拼接到新的路由
*
* @param obj 一个对应,使用 qs 压缩后作为新路由的查询参数跳转
* @param navOption 同 React Route V6 的 useNavigate 返回值的配置,用于路由跳转
*/
const navQs = useCallback(
(obj: T | ((t: T) => T), navOption?: NavigateOptions) => {
const objToSerialize = typeof obj === "function" ? obj(query) : obj;
const str = qs.stringify(objToSerialize, optionsRef.current.stringifyOptions);
navigate({ search: str }, navOption);
},
[navigate, query]
);
return [query, navQs] as const;
}
useQs 文档
useQs hook 用来对 qs 库进行 hook 调用,并集成到 react router v6 当中。它提供很简单的方式来管理当前页面的查询参数。
其基础用处如下:
const [qsValue, setQsValue] = useQs({ defaultParam: "defaultValue" });
// 当你需要获取本页面的查询参数时
console.log(qsValue);
// 当你需要设置当前页面的查询参数并用 react router 跳转时
setQsValue({ defaultParam: "newValue" });
参数
useQs 接收两个参数:
useQs(def, qsOptions);
需要注意的是,这两个参数都使用 ref 一次性存储,不会依赖更新。
def
def
参数作为当前地址的默认查询参数。
例如地址 http://host.com/url
,下面代码依旧能正常运行:
const [qs, setQs] = useQs({ currentPage: "1" });
console.log(qs); // { currentPage: "1" }
例如地址 http://host.com/url?currentPage=2&foo[bar]=baz
,获取到的值就会发生变化:
const [qs, setQs] = useQs({ currentPage: "1" });
console.log(qs); // { currentPage: "2", foo: { bar: "baz" }}
默认值会被会被 url 上的查询参数进行逐一覆盖。
qsOptions
qsOptions 用于配置 qs 的解析和序列化配置
qsOptions.parseOptions
:解析配置qsOptions.stringifyOptions
:序列化配置
上述配置参考 qs 文档
返回值
useQs 返回只有两个值的元组,类似 useState 一样:
const [qsValue, setQsValue] = useQs();
-
qsValue
:是当前路由的查询参数经过 qs 库解析后的对象。 -
setQsValue
:是用来设置新的查询参数的函数。
qsValue
qsValue
是一个缓存值,使用 qs 库对当前路由查询参数解析后,再覆盖默认值得到。
qsValue 依赖 react router 的 useLocation 更新。
setQsValue
setQsValue 用来更新当前路由,例如:
setQsValue({ foo: { bar: "baz" }, param: "1" }); // ?foo[bar]=baz¶m=1
它还有第二个参数,用来设置 ReactRouterV6 路由的配置,例如:
// 这将重定向路由
setQsValue({ foo: "1" }, { replace: true });