當我剛接手 React 專案的時候,就對整體專案代碼看了一遍,其中就有一個命名為 customer-hooks,打開一看,全都是命名為 usexxx 的 jsx 檔案,后面了解到這是大佬們封裝的自定義 hook,
于是,今天就自己來總結一下對于 Custom React Hooks 一些思考,

自定義 Hook
以下來自 React 官網 關于自定義 Hook 的介紹:
與 React 組件不同的是,自定義 Hook 不需要具有特殊的標識,我們可以自由的決定它的引數是什么,以及它應該回傳什么(如果需要的話),換句話說,它就像一個正常的函式,但是它的名字應該始終以 use 開頭,這樣可以一眼看出其符合 Hook 的規則,
而對于 Hook 的規則:
- 不要在回圈,條件或嵌套函式中呼叫 Hook, 確保總是在你的 React 函式的最頂層以及任何 return 之前呼叫他們,
- 只在 React 函式中呼叫 Hook
自定義 Hook 封裝了一些邏輯代碼,并能夠把資料向下傳遞到渲染樹的操作,
啟動一個 react 專案
可以通過如下命令快速創建簡單 react 應用,詳細步驟可以參考官網,
npx create-react-app react-demo
簡單的例子
下面撰寫我們自定義的 Hook,本人還是比較菜雞,所以就拿阿里的 ahooks 官方檔案 學習了,在 src 檔案目錄下創建如下目錄結構,用來存放我們的自定義 hook,

代碼是來自于 ahooks github 倉庫地址
PS:這里就不粘貼原始碼了,大家可以在上述地址拿到,
我們的父組件代碼如下:
import SubApp from './subApp';
import useBoolean from './custom-hooks/useBoolean/index';
function App() {
const [state, { toggle, setTrue, setFalse }] = useBoolean(true);
return (
<div>
<p>Effects:{JSON.stringify(state)}</p>
<p>
<button type="button" onClick={() => toggle()}>
Toggle
</button>
<button type="button" onClick={setFalse} style={{ margin: '0 16px' }}>
Set false
</button>
<button type="button" onClick={setTrue}>
Set true
</button>
</p>
<SubApp />
</div>
)
}
export default App;
通過 npm start 啟動專案,可以看到如下界面:

可以看到,使用了自定義 Hook,我們會省去很多重復性的邏輯代碼,在父子組件我們都可以使用自定義的 hook,
思考一
但是,我就有問題了,雖然自定義 hook 很香,但發現沒有,當我們重新渲染的時候,這一整塊邏輯代碼也會跟著運行,如果它的運行可以忽略不計倒還好,但還是要考慮一下萬一情況,比如你運行了很多個 hook 呢?
想了想,既然這個 useBoolean 是依賴于回傳的 state,那么是不是可以通過 useMemo 來解決問題,
查看 ahooks 原始碼,果然,就有通過 useMemo 來處理的:
const actions = useMemo(() => {
const reverseValueOrigin = (reverseValue === undefined ? !defaultValue : reverseValue) as D | R;
// 切換回傳值
const toggle = (value?: D | R) => {
// 強制回傳狀態值,適用于點擊操作
if (value !== undefined) {
setState(value);
return;
}
setState((s) => (s === defaultValue ? reverseValueOrigin : defaultValue));
};
// 設定默認值
const setLeft = () => setState(defaultValue);
// 設定取反值
const setRight = () => setState(reverseValueOrigin);
return {
toggle,
setLeft,
setRight,
};
}, [defaultValue, reverseValue]);
思考二
上述我是有父子組件,它們都呼叫了自定義 Hook ,那么我想的是它們會共享狀態嘛,畢竟都是回傳 state,那么假設我改了父組件的 state,那么子組件也會跟著變嗎?
帶著好奇心,我操作了一下界面,將父組件呼叫一下 toggle 方法,結果如下:

在此基礎上,我再呼叫一下父組件的 setTrue 方法試試,結果如下:

發現,并不會因為多個組件呼叫同一個自定義 Hook 而共享狀態,
來自 React 官網 的表述:
自定義 Hook 是一種重用狀態邏輯的機制(例如設定為訂閱并存盤當前值),所以每次使用自定義 Hook 時,其中的所有 state 和副作用都是 完全隔離 的,
那么自定義 Hook 如何獲取獨立的 state?
每次呼叫 Hook,它都會獲取獨立的 state,由于我們直接呼叫了 useBoolean,從 React 的角度來看,我們的組件只是呼叫了 useState 和 useMemo,
我們可以在一個組件中多次呼叫 useState 和 useEffect等,它們是完全獨立的,
那么,結合官方的說法,理解起來就容易多了,其實我們可以這樣想,每次呼叫會回傳一個新的實體,如下述我們使用 useBoolean 代碼:
const [state, { toggle, setTrue, setFalse }] = useBoolean(true);
其實可以想象成回傳新的實體,每個實體都會開一個新的空間存放,那么每個組件參考的那個實體都是完全獨立開的,所以就不存在狀態共享了,放心使用,
思考三
既然狀態隔離了,我在想有啥辦法能夠共享狀態呢?
我想有時候也得需要在組件之間共享狀態的,
于是,我又翻了翻公司代碼以及問了我導師,我發現居然使用了 context,那么,就得研究一下 context 的一些用法,
結尾
為了讓文章少點廢話,讓大家在簡短的時間內能夠吸收知識,本篇內容就先到此了,下一篇我們將講解 React Context 的一些使用方法,來解決上文的思考,
關于本文內容,也歡迎和大家交流討論,
我是【一百個Chocolate】,如果喜歡的話,可以給本文點個贊,我們下期再見啦~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/305704.html
標籤:其他
上一篇:JavaScript事件流
