成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

讓我們一起聊聊封裝一個(gè)管理 Url 狀態(tài)的 Hook

開發(fā) 開發(fā)工具
工具庫中假如某個(gè)工具函數(shù)/hook 依賴于一個(gè)開發(fā)者可能并不會(huì)使用的包,而且這個(gè)包的體積還比較大的時(shí)候,可以將這個(gè)工具函數(shù)/hook 獨(dú)立成一個(gè) npm 包,開發(fā)者使用的時(shí)候才進(jìn)行安裝。

本文來講下 ahooks 中的 useUrlState。

通過 url query 來管理 state 的 Hook。

useUrlState 的特殊

在之前的架構(gòu)篇中我們就提到,ahooks 這個(gè)項(xiàng)目是一個(gè) monoRepo。它的項(xiàng)目管理是通過 lerna[1] 進(jìn)行管理的。可以從官網(wǎng)以及源碼中看到 useUrlState 是獨(dú)立一個(gè)倉庫進(jìn)行管理的。

也就是你必須單獨(dú)安裝:

npm i @ahooksjs/use-url-state -S

我認(rèn)為官方這么做的理由是 useUrlState 基于 react-router 的 useLocation & useHistory & useNavigate 進(jìn)行 query 管理。所以你必須要安裝 react-router 的 5.x 或者 6.x 版本。但其實(shí)很多 React 項(xiàng)目都不一定使用 react-router。假如將這個(gè) hook 內(nèi)置到 ahooks 中的話,可能會(huì)導(dǎo)致包體積變大。

圖片

另外,該 hook 是依賴于 query-string 這個(gè) npm 包的。使用這個(gè)包,我認(rèn)為理由有以下幾點(diǎn):

  • 一來是其功能強(qiáng)大,支持很多的 options 選項(xiàng),滿足我們各類業(yè)務(wù)需求。
  • 二來它業(yè)內(nèi)也比較成熟,避免重復(fù)造輪子。
  • 三來它的包體積也很小,沒什么負(fù)擔(dān)。我們主要用到它的 parse 和 stringify 方法,壓縮后只有 2.4 k。

圖片

通過示例簡單介紹下,這兩個(gè)方法:

qs.parse(string, [options])

qs.parse('?name=jim')  // {name: 'jim'}
qs.parse('#token=123') // {token: '123'}
qs.parse('name=jim&name=lily&age=22') // {name: ['jim', 'lily'], age: 22}
qs.parse('foo[]=1&foo[]=2&foo[]=3', {arrayFormat: 'bracket'});
//=> {foo: ['1', '2', '3']}

qs.stringify(object, [options])

qs.stringify({name: 'jim', age: 22});  // 'age=22&name=jim'
qs.stringify({name: ['jim', 'lily'], age: 22}); // 'age=22&name=jim&name=lily'
qs.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket'});
//=> 'foo[]=1&foo[]=2&foo[]=3'

useUrlState 源碼解析

直接看代碼,顯示初始值部分。

  • 第一個(gè)參數(shù)為初始狀態(tài),第二個(gè)參數(shù)為 url 的配置,包括狀態(tài)變更時(shí)切換 history 的方式、query-string parse 和  stringify 的配置。
  • 通過 react-router 的 useLocation 獲取到 URL 的 location 對(duì)象。
  • react-router 兼容 5.x 和 6.x,其中 5.x 使用 useHistory,6.x 使用 useNavigate。
  • queryFromUrl 是調(diào)用 query-string 的 parse 方法,將 location 對(duì)象的 search 處理成對(duì)象值。
  • targetQuery 就是處理之后的最終值-將 queryFromUrl 和初始值進(jìn)行 merge 之后的結(jié)果。
// ...
import * as tmp from 'react-router';
// ...
const useUrlState = <S extends UrlState = UrlState>(
// 初始狀態(tài)
initialState?: S | (() => S),
// url 配置
options?: Options,
) => {
type State = Partial<{ [key in keyof S]: any }>;
const {
// 狀態(tài)變更時(shí)切換 history 的方式
navigateMode = 'push',
// query-string parse 的配置
parseOptions,
// query-string stringify 的配置
stringifyOptions,
} = options || {};

const mergedParseOptions = { ...baseParseConfig, ...parseOptions };
const mergedStringifyOptions = { ...baseStringifyConfig, ...stringifyOptions };

// useLocation鉤子返回表示當(dāng)前URL的location對(duì)象。您可以將它想象成一個(gè)useState,它在URL更改時(shí)返回一個(gè)新值。
const location = rc.useLocation();

// https://v5.reactrouter.com/web/api/Hooks/usehistory
// useHistory 鉤子可以訪問用來導(dǎo)航的歷史實(shí)例。
// react-router v5
const history = rc.useHistory?.();
// react-router v6
const navigate = rc.useNavigate?.();

const update = useUpdate();

const initialStateRef = useRef(
typeof initialState === 'function' ? (initialState as () => S)() : initialState || {},
);

// 根據(jù) url query
const queryFromUrl = useMemo(() => {
return parse(location.search, mergedParseOptions);
}, [location.search]);

const targetQuery: State = useMemo(
() => ({
...initialStateRef.current,
...queryFromUrl,
}),
[queryFromUrl],
);
// 省略部分代碼
}

接下來看 url 的狀態(tài)設(shè)置:

  • 首先是根據(jù)傳入的 s 值,獲取到新的狀態(tài) newQuery,支持 function 方式。
  • 根據(jù)不同的 react-router 的版本調(diào)用不同的方法進(jìn)行更新。

假如是 5.x 版本,調(diào)用 useHistory 方法,更新對(duì)應(yīng)的狀態(tài)。

假如是 6.x 版本,調(diào)用 useNavigate 方法,更新對(duì)應(yīng)的狀態(tài)。

  • 通過 update() -useUpdate() 更新狀態(tài)。
// 設(shè)置 url 狀態(tài)
const setState = (s: React.SetStateAction<State>) => {
const newQuery = typeof s === 'function' ? s(targetQuery) : s;
// 1. 如果 setState 后,search 沒變化,就需要 update 來觸發(fā)一次更新。比如 demo1 直接點(diǎn)擊 clear,就需要 update 來觸發(fā)更新。
// 2. update 和 history 的更新會(huì)合并,不會(huì)造成多次更新
update();
if (history) {
history[navigateMode]({
hash: location.hash,
search: stringify({ ...queryFromUrl, ...newQuery }, mergedStringifyOptions) || '?',
});
}
if (navigate) {
navigate(
{
hash: location.hash,
search: stringify({ ...queryFromUrl, ...newQuery }, mergedStringifyOptions) || '?',
},
{
replace: navigateMode === 'replace',
},
);
}
};

思考與總結(jié)

工具庫中假如某個(gè)工具函數(shù)/hook 依賴于一個(gè)開發(fā)者可能并不會(huì)使用的包,而且這個(gè)包的體積還比較大的時(shí)候,可以將這個(gè)工具函數(shù)/hook 獨(dú)立成一個(gè) npm 包,開發(fā)者使用的時(shí)候才進(jìn)行安裝。另外這種可以考慮使用 monoRepo 的包管理方法,方便進(jìn)行文檔管理以及一些公共包管理等。

責(zé)任編輯:武曉燕 來源: 前端雜貨鋪
相關(guān)推薦

2021-08-27 07:06:10

IOJava抽象

2022-06-26 09:40:55

Django框架服務(wù)

2022-02-14 07:03:31

網(wǎng)站安全MFA

2021-07-31 11:40:55

Openresty開源

2023-08-02 08:35:54

文件操作數(shù)據(jù)源

2022-08-01 07:57:03

數(shù)組操作內(nèi)存

2022-08-30 13:48:16

LinuxMySQL內(nèi)存

2021-11-04 06:58:31

CSS性能設(shè)備

2021-11-09 23:54:19

開發(fā)SMI Linkerd

2022-12-05 09:10:21

2021-10-26 09:55:52

CAP理論分布式

2022-03-15 20:18:35

單元測試工具

2022-08-29 07:48:27

文件數(shù)據(jù)參數(shù)類型

2023-11-30 07:40:05

URLCMS

2021-12-29 08:27:05

ByteBuffer磁盤服務(wù)器

2022-03-08 17:52:58

TCP格式IP

2022-03-31 18:59:43

數(shù)據(jù)庫InnoDBMySQL

2021-11-15 11:03:09

接口壓測工具

2024-08-02 09:49:35

Spring流程Tomcat

2024-06-17 11:59:39

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 毛片久久久 | 天天操天天操 | 欧美一级片黄色 | 中文字幕91 | 国产在线小视频 | 日本一卡精品视频免费 | 亚洲视频一区在线观看 | 午夜免费视频 | 一区视频| 欧美日韩一区在线观看 | 欧美在线视频网 | 这里只有精品999 | 日韩毛片播放 | 操操日 | 精品国产一区二区三区久久狼黑人 | 国产精品久久久久久久久久免费 | 色爱区综合 | 国产黄色小视频 | 精品亚洲视频在线 | 欧美爱爱视频 | 一级做a爰片性色毛片16美国 | 99精品国产成人一区二区 | 日韩欧美在线精品 | 欧美三级三级三级爽爽爽 | 波多野结衣一区二区 | 午夜影视 | 国产四虎| 中文一区二区 | 久久免费看 | 国产农村一级国产农村 | 国产精品欧美大片 | 精品久久久久久久久久久院品网 | 欧美一级免费 | 中文字幕精品一区久久久久 | 四色成人av永久网址 | 久久久www成人免费精品 | 操视频网站 | 国产在线一区观看 | 免费在线性爱视频 | 午夜小电影 | 欧产日产国产精品国产 |