重复造了个轮子,另写一个 use-url-state hooks 来管理 URL 的查询参数

123 阅读3分钟

我是一个半桶水的后端开发,偶尔写点前端页面,自称为全栈(干)工程师

最近看到一篇文章说 Farm 很吊,然后就想把当前的 UMI MAX Ant Design Pro 迁移到 Farm,但是在尝试迁移的过程中发现要改的东西好像有点多,特别是路由这一块,折腾了 React-Router V7 挺久,无果,然后尝试换成 TanStack Router

在尝试迁移一些页面的时候发现,我代码中用了 @ahooksjs/use-url-state 这个库来读取 URL 地址的查询参数信息,但是 @ahooksjs/use-url-state 是基于 React-Router 来开发的,没办法在 TanStack Router 上使用。

然后去 npmjs 上查了一些已经发布的现有库,发现 github.com/dean177/use…www.npmjs.com/package/@um… 这两个库,但看示例都是对 window.location.search 的数据进行读写的,没有对 window.location.hash 的查询参数进行读写的。

所以想自己尝试去写一个库试试看,可用来管理 window.location.searchwindow.location.hash 的查询参数。想尽量少的引入第三方库,以及使用 URLSearchParams 来解析参数信息。

也许、应该、虽然、可能 没有别人的库好用,但也算是一种新的尝试。

Hooks 列表

有以下6个hooks

  • useUrlParamsState :
    • window.location.searchwindow.location.hash 中读取参数,返回 URLSearchParams 类型参数对象
  • useUrlState :
    • window.location.searchwindow.location.hash 中读取参数,返回普通参数对象
  • useUrlHashParamsState :
    • window.location.hash 中读取参数,返回 URLSearchParams 类型参数对象
  • useUrlHashState :
    • window.location.hash 中读取参数,返回普通参数对象
  • useUrlSearchParamsState :
    • window.location.search 中读取参数,返回 URLSearchParams 类型参数对象
  • useUrlSearchState :
    • window.location.search 中读取参数,返回普通参数对象

Hooks 关系说明

useUrlSearchParamsStateuseUrlHashParamsState 是原始用法支撑。

useUrlParamsState 是合并 useUrlSearchParamsStateuseUrlHashParamsState 的用法到一个 hooks 里面。

useUrlSearchParamsState 返回的是 URLSearchParams 对象,useUrlSearchState 对其做了一次封装转换,使返回值为普通对象。

useUrlHashParamsState 返回的是 URLSearchParams 对象,useUrlHashState 对其做了一次封装转换,使返回值为普通对象。

useUrlParamsState 返回的是 URLSearchParams 对象,useUrlState 对其做了一次封装转换,使返回值为普通对象。

基本类型

export type UrlState = Record<string, string | number | null | undefined | (string | number | null | undefined)[]>;
export type UrlParamsState = UrlState | URLSearchParams;
export type UseUrlHashParamsStateOptions = {
  /**
   * 初始参数是否设置到 hash
   */
  initParamsToHash?: boolean;
};
export type UseUrlSearchParamsStateOptions = {
  /**
   * 初始参数是否设置到 search
   */
  initParamsToSearch?: boolean;
};
export type UseUrlParamsStateOptions = {
  /**
   * 新参数追加到路径的位置:search | hash,默认追加到 hash 位置
   */
  newParamsLocation?: 'search' | 'hash';
} & UseUrlSearchParamsStateOptions &
  UseUrlHashParamsStateOptions;

普通对象返回值的说明

所有 hooks 的入参 UrlState 初始化参数支持一级数组参数,但 useUrlSearchState useUrlHashState useUrlState 返回的普通对象会经过特殊处理。

其中 ''(空字符串) null undefined [] [''] [null] [undefined] 都将被序列化成空字符串 '' 值,解析也将按照空字符串来处理。

如果数组仅有 1 个值时,不以数组形式返回,如果参数 key 以 [] 中括号结尾(例如:userIds[])则强制以数组形式返回。

image.png

一些示例用法

import useUrlState, {
  useUrlParamsState,
  useUrlHashParamsState,
  useUrlHashState,
  useUrlSearchParamsState,
  useUrlSearchState,
} from '@houkunlin/use-url-state';

const [query, setQuery, { searchQuery, hashQuery, setSearchQuery, setHashQuery }] = useUrlState();
useUrlState({ count: 0, page: 1, ids: [1, 2], 'pids[]': [1, 2] });
useUrlState({ count: 0 }, { page: 1 });
useUrlState({ count: 0 }, { page: 1 }, { newParamsLocation: 'hash', initParamsToSearch: true, initParamsToHash: true });

const [query, setQuery, { searchQuery, hashQuery, setSearchQuery, setHashQuery }] = useUrlParamsState();
useUrlParamsState({ count: 0, page: 1 });
useUrlParamsState({ count: 0 }, { page: 1 });
useUrlParamsState(
  { count: 0 },
  { page: 1 },
  {
    newParamsLocation: 'search',
    initParamsToSearch: true,
    initParamsToHash: true,
  },
);
useUrlParamsState(new URLSearchParams('count=0&page=1'));
useUrlParamsState(new URLSearchParams('count=0'), new URLSearchParams('page=1'));
useUrlParamsState(new URLSearchParams('count=0'), new URLSearchParams('page=1'), {
  newParamsLocation: 'search',
  initParamsToSearch: true,
  initParamsToHash: true,
});

const [query, setQuery] = useUrlHashState();
const [query, setQuery] = useUrlHashState({ count: 0, page: 1, ids: [1, 2], 'pids[]': [1, 2] });
const [query, setQuery] = useUrlHashState({ count: 0, page: 1 }, { initParamsToHash: true });

const [query, setQuery] = useUrlHashParamsState();
const [query, setQuery] = useUrlHashParamsState({ count: 0, page: 1 });
const [query, setQuery] = useUrlHashParamsState({ count: 0, page: 1 }, { initParamsToHash: true });
const [query, setQuery] = useUrlHashParamsState(new URLSearchParams('count=0&page=1'));
const [query, setQuery] = useUrlHashParamsState(new URLSearchParams('count=0&page=1'), { initParamsToHash: true });

const [query, setQuery] = useUrlSearchState();
const [query, setQuery] = useUrlSearchState({ count: 0, page: 1, ids: [1, 2], 'pids[]': [1, 2] });
const [query, setQuery] = useUrlSearchState({ count: 0, page: 1 }, { initParamsToSearch: true });

const [query, setQuery] = useUrlSearchParamsState();
const [query, setQuery] = useUrlSearchParamsState({ count: 0, page: 1 });
const [query, setQuery] = useUrlSearchParamsState({ count: 0, page: 1 }, { initParamsToSearch: true });
const [query, setQuery] = useUrlSearchParamsState(new URLSearchParams('count=0&page=1'));
const [query, setQuery] = useUrlSearchParamsState(new URLSearchParams('count=0&page=1'), { initParamsToSearch: true });

文档地址

详细文档请查看 use-url-state.pages.dev/components