ahooks的useRequest源碼解讀
“ ahooks是一套高質(zhì)量的hooks庫(kù),在React開發(fā)的過程,能夠省下很多冗余代碼,提高開發(fā)效率”
在開啟本文 ahooks 之前,首先要先了解一下什么是 React hooks
React hooks 是 React 在 16.8 版本之后推出的新功能,它的出現(xiàn)讓 函數(shù)式組件 不再是 無狀態(tài)組件,而是 擁有狀態(tài) 以及 副作用。
舉個(gè)例子,以前寫一個(gè)計(jì)數(shù)器組件,是這樣的格式

上面的代碼,假如用函數(shù)的形式,那么是無法在組件里維護(hù) num 這個(gè)數(shù)量的,也無法在組件里改變 num,在 num 變化時(shí)做出處理。最多只能通過 props,從父組件控制它,例如下面:

但是 hooks 出現(xiàn)之后,我們就可以在函數(shù)組件里維護(hù)狀態(tài)和副作用。例如下面代碼所示,就可以通過 useState 來維護(hù)一個(gè)狀態(tài) num,用 useEffect 在 num變化時(shí)做出一些處理

hooks的好處還不止體現(xiàn)在這里,還體現(xiàn)在它可以 抽離共用邏輯。例如系統(tǒng)里有很多組件都需要設(shè)置 localStorage ,那其實(shí)可以寫一個(gè) useLocalStorage 來實(shí)現(xiàn)邏輯復(fù)用

使用的時(shí)候就可以:

這樣的復(fù)用非常實(shí)用,而且大大減少了代碼量。所以很多人嘗試去抽離一些通用的邏輯出來,組成一個(gè)庫(kù),而 ahooks,就是這樣的一個(gè) hooks 庫(kù)
01
—
ahooks
ahooks,官網(wǎng)定義為一個(gè)高質(zhì)量可靠的 React hooks 庫(kù)

事實(shí)上也確實(shí)如此,React的開發(fā)中用上hooks,會(huì)讓業(yè)務(wù)邏輯更加簡(jiǎn)潔易寫,比較有代表性的hooks比如:
useRequest
useAsyncEffect
useDebounceFn
useThrottleFn
其中,最為常用的就是 useRequest
02
—
useRequest
首先看到 packages/hooks/src/useRequest/src/useRequest.ts 里面的代碼,發(fā)現(xiàn)它其實(shí)是返回了另一個(gè)函數(shù) useRequestImplement

這時(shí)候,我們跳到 useRequestImplement 方法里面查看具體寫了什么:

在這里出現(xiàn)了很多新的 hooks,我們暫時(shí)不管,關(guān)注 fetchInstance這個(gè)實(shí)例,實(shí)際上是由 new Fetch 生成的,這個(gè)實(shí)例的對(duì)應(yīng)關(guān)系如下圖:
| loading |
fetchInstance.state.loading |
| data |
fetchInstance.state.data |
| error |
fetchInstance.state.error |
| params |
fetchInstance.state.params |
| cancel |
fetchInstance.cancel |
| refresh |
fetchInstance.refresh |
| refreshAsync |
fetchInstance.refreshAsync |
| run |
fetchInstance.run |
| mutate |
fetchInstance.mutate |
那接下來,我們就著重看下 Fetch 這個(gè)類
03
—
Fetch類

這里內(nèi)容有點(diǎn)多,我們先看下 Fetch 類型里面維護(hù)的狀態(tài):

loading:表示當(dāng)前是否還在請(qǐng)求中
params:代表請(qǐng)求攜帶的參數(shù)
data:請(qǐng)求返回的數(shù)據(jù)
error:請(qǐng)求過程中如果throw Error的話,就會(huì)到這個(gè)字段中
有了這些初始狀態(tài),我們就要開始請(qǐng)求了,最核心的方法就是 runAsync 方法
04
—
runAsync方法

這里面可以看到是按照 onBefore 、onRequest、onSuccess、onError、onFinally 這個(gè)流程串聯(lián)起來的。實(shí)際上真正發(fā)起請(qǐng)求的只有這一段

通過調(diào)用 this.runPluginHandler 來執(zhí)行各個(gè)時(shí)期的回調(diào)函數(shù)。而 this.runPluginHandler 實(shí)際也是遍歷執(zhí)行傳遞進(jìn)來的插件函數(shù)

看懂上面這段 runAsync 代碼之后,run 的代碼也很容易理解了

05
—
cancel方法
上面講的都是如何用 run 方法進(jìn)行請(qǐng)求,那假如我請(qǐng)求中途想取消怎么辦呢。
這里開頭維護(hù)了一個(gè) count 變量,每次 run 的時(shí)候就賦值給 currentCount,并且 +1。到最后請(qǐng)求結(jié)束之后,會(huì)比對(duì) count 和當(dāng)前的數(shù)字是否一致,假如不一致,那說明就不是同一次請(qǐng)求,返回一個(gè)空的 Promise

cancel 方法利用了這個(gè)原理,每次調(diào)用cancel的時(shí)候,就把count + 1,那最后對(duì)比肯定就不一致了。起到了取消的效果

06
—
mutate方法
使用上面 run 方法,我們完成正常請(qǐng)求過程。但是有時(shí)候我們可能想立刻改變數(shù)據(jù),而不是等待請(qǐng)求返回,useRequest 提供了一個(gè) “立刻改變數(shù)據(jù)” 的方法,叫mutate,原理也很簡(jiǎn)單,直接使用傳入的值,或者函數(shù)進(jìn)行賦值。這里就直接貼上源碼

07
—
refresh方法
refresh 方法實(shí)際上也是重新跑了一次 run

以上就是 useRequest 源碼分析的全部?jī)?nèi)容,歡迎大家點(diǎn)贊和評(píng)論
