自定義Hooks可以讓你把組件邏輯抽到可復用的方法里。
當我們學effect hooks的時候,我們用這個組件來顯示朋友是否在線
現在假設我們的聊天應用還有一個聯繫人列表,我們想要把在線用戶的名字用綠色顯示。我們可以複製粘貼相同的邏輯到FriendListItem組件中,但這麼做不是最合適的
所以我們應該在FriendStatus和FriendListItem之間共享邏輯。
一般在React中,我們有兩種流行的方式來共享有狀態邏輯——render props和高階組件。我們來看一下Hooks在不需要更多關注組件的情況下怎麼來解決這個問題。
當我們想要在JavaScript方法里復用邏輯時,我們會把它抽取到第三方的方法里。組件和Hooks本質上都是方法,所以同樣適用。
自定義Hook是一個用use開頭命名的JavaScript方法,它能調其他Hooks。比如下面的useFriendStatus是我們第一個自定義Hook
裡面沒有新的東西——就複製了組件里的邏輯。跟在組件里一樣,保證只在自定義Hook的頂層調用其他Hooks。
跟React組件不同的是,自定義Hook不需要有特殊的方法簽名。我們可以自己決定有什麼參數和返回。換句話說,它就跟普通的方法完全一樣。它的名字應該用use開頭。
我們的useFriendStatus目的是訂閱朋友的在線狀態。它接受friendID作為傳入參數,返回朋友是否在線的狀態。
現在讓我們看看如何使用自定義Hook。
一開始,我們的目標是移除在FriendStatus和FriendListItem之間的重複邏輯。它們都是想要獲得某個朋友是否在線。
現在我們把邏輯抽到了useFriendStatus里
這代碼和之前的例子作用相同嗎?是的,完全一樣。如果你仔細看,你會發現我們對行為根本沒做任何變化。所做的就僅是抽取公共代碼到獨立的方法里。自定義Hooks就是一個遵循Hooks設計的約定,而不是React的特性。
我是否必須把自定義Hook的命名用use開頭?請如此做。這個約定非常重要。不這樣,我們沒法按照Hooks使用規則這一章所闡述的來檢查代碼,因為沒法判斷某個方法是否在裡面調用了Hooks。
兩個使用相同Hook的組件是否共享了state?不。自定義Hooks是一個復用有狀態邏輯的機制(比如訂閱和記憶當前值),但每次你使用自定義Hook的時候,所有其中的stat和effect是獨立的。
自定義Hook如何獲得獨立state的?每一次調用Hook都獲得的是獨立的state。因為我們是直接調useFriendStatus的,從React的角度看我們僅是調用了useState和useEffect。如我們之前所學,我們可以在一個組件里調用useState和useEffect多次,每次都是完全獨立的結果。
因為Hooks就是一個方法,我們可以在它們之間傳遞消息。
我們用聊天例子中的另一個組件來說明。這是一個聊天消息接收選擇器用來顯示當前所選朋友是否在線的。
我們用recipientID狀態變數來保存當前選中的朋友ID,如果用戶在<select>選擇另一個朋友的時候更新它。
由於useState返回給我們最新的recipientID狀態變數數據,我們可以把它作為一個參數傳遞給自定義Hook。
這就能讓我們知道當前選中的朋友是否在線。如果我們選擇了另一個朋友並更新了recipientID狀態變數,我們的useFriendStatus就能取消訂閱之前的朋友並訂閱新選擇的朋友狀態。
自定義Hooks提供了在React組件里不曾有的共享邏輯的靈活性。你可以把自定義Hooks用在很多地方,比如表單處理、動畫、聲明式訂閱、定時處理以及我們之前都沒想到過的方向上。另外,你可以用Hooks像用React內置特性一樣簡單。
不要太早地去抽象。現在function組件可以干更多的事情,你代碼庫里的funtion組件代碼將會變得更長。這很正常——不要覺得你必須立刻把什麼都抽到Hooks裡面去。但我們鼓勵你開始去看看Hooks是如何把複雜的邏輯隱藏到簡單的介面後去的,以及如何幫助簡化一個複雜的組件。
例如,假使你有一個複雜的組件包含了很多的點對點的內部state。useState不會把集中更新邏輯變得簡單,所以你可能會考慮用Redux的reducer的方式
Reducer可以方便的獨立測試,合起來可以處理複雜的更新邏輯。必要的話你可以把它們拆到小的reducer中去。但是你也可以用React內部state來享受它的方便性,或者你可能不想再啟用一個第三方的庫。
我們如何寫一個useReducer Hook來管理組件里的內部state?一個簡單的版本如下
現在我們可以把它用在組件里,用reducer來驅動狀態管理
這個在複雜組件里用reducer管理內部state的需求比較普遍所以我們在React里已經包含了一個叫useReducer的Hook。
TAG:React | 前端開發 | 前端框架 |