一文歸納 React Hooks 常用場景

前言

React 在 v16.8 的版本中推出了 React Hooks 新特性。在我看來器贩,使用 React Hooks 相比于從前的類組件有以下幾點好處:

代碼可讀性更強,原本同一塊功能的代碼邏輯被拆分在了不同的生命周期函數(shù)中衔统,容易使開發(fā)者不利于維護和迭代提针,通過 React Hooks 可以將功能代碼聚合,方便閱讀維護施敢;

組件樹層級變淺周荐,在原本的代碼中,我們經(jīng)常使用 HOC/render props 等方式來復用組件的狀態(tài)僵娃,增強功能等概作,無疑增加了組件樹層數(shù)及渲染,而在 React Hooks 中默怨,這些功能都可以通過強大的自定義的 Hooks 來實現(xiàn)讯榕;

關于這方面的文章,我們根據(jù)使用場景分別進行舉例說明匙睹,幫助你認識理解并可以熟練運用 React Hooks 大部分特性愚屁。

辛苦整理良久,還望手動點贊鼓勵~

博客 github地址為:github.com/fengshi123/… 痕檬,匯總了作者的所有博客集绰,歡迎關注及 star ~

一、State Hook

1谆棺、基礎用法

2栽燕、更新

更新分為以下兩種方式,即直接更新和函數(shù)式更新改淑,其應用場景的區(qū)分點在于:

直接更新不依賴于舊 state 的值碍岔;

函數(shù)式更新依賴于舊 state 的值;

3朵夏、實現(xiàn)合并

與 class 組件中的 setState 方法不同蔼啦,useState 不會自動合并更新對象,而是直接替換它仰猖。我們可以用函數(shù)式的 setState 結合展開運算符來達到合并更新對象的效果捏肢。

4奈籽、惰性初始化 state

initialState 參數(shù)只會在組件的初始渲染中起作用,后續(xù)渲染時會被忽略鸵赫。其應用場景在于:創(chuàng)建初始 state 很昂貴時衣屏,例如需要通過復雜計算獲得;那么則可以傳入一個函數(shù)辩棒,在函數(shù)中計算并返回初始的 state狼忱,此函數(shù)只在初始渲染時被調(diào)用:

5、一些重點

(1)不像 class 中的 this.setState 一睁,Hook 更新 state 變量總是替換它而不是合并它钻弄; (2)推薦使用多個 state 變量,而不是單個 state 變量者吁,因為 state 的替換邏輯而不是合并邏輯窘俺,并且利于后續(xù)的相關 state 邏輯抽離; (3)調(diào)用 State Hook 的更新函數(shù)并傳入當前的 state 時复凳,React 將跳過子組件的渲染及 effect 的執(zhí)行批销。(React 使用 Object.is 比較算法 來比較 state。)

二染坯、Effect Hook

1均芽、基礎用法

2、清除操作

為防止內(nèi)存泄漏单鹿,清除函數(shù)會在組件卸載前執(zhí)行掀宋;如果組件多次渲染(通常如此),則在執(zhí)行下一個 effect 之前仲锄,上一個 effect 就已被清除劲妙,即先執(zhí)行上一個 effect 中 return 的函數(shù),然后再執(zhí)行本 effect 中非 return 的函數(shù)儒喊。

3镣奋、執(zhí)行時期

與 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 調(diào)度的 effect 不會阻塞瀏覽器更新屏幕怀愧,這讓你的應用看起來響應更快侨颈;(componentDidMount 或 componentDidUpdate 會阻塞瀏覽器更新屏幕)

4、性能優(yōu)化

默認情況下芯义,React 會每次等待瀏覽器完成畫面渲染之后延遲調(diào)用 effect哈垢;但是如果某些特定值在兩次重渲染之間沒有發(fā)生變化,你可以通知 React 跳過對 effect 的調(diào)用扛拨,只要傳遞數(shù)組作為 useEffect 的第二個可選參數(shù)即可:如下所示耘分,如果 count 值兩次渲染之間沒有發(fā)生變化,那么第二次渲染后就會跳過 effect 的調(diào)用;

5求泰、模擬 componentDidMount

如果想只運行一次的 effect(僅在組件掛載和卸載時執(zhí)行)央渣,可以傳遞一個空數(shù)組([ ])作為第二個參數(shù),如下所示渴频,原理跟第 4 點性能優(yōu)化講述的一樣芽丹;

6、最佳實踐

要記住 effect 外部的函數(shù)使用了哪些 props 和 state 很難枉氮,這也是為什么 通常你會想要在 effect 內(nèi)部 去聲明它所需要的函數(shù)。

如果出于某些原因你無法把一個函數(shù)移動到 effect 內(nèi)部暖庄,還有一些其他辦法:

你可以嘗試把那個函數(shù)移動到你的組件之外聊替。那樣一來,這個函數(shù)就肯定不會依賴任何 props 或 state培廓,并且也不用出現(xiàn)在依賴列表中了惹悄;

萬不得已的情況下,你可以 把函數(shù)加入 effect 的依賴但 把它的定義包裹 進 useCallback Hook肩钠。這就確保了它不隨渲染而改變泣港,除非它自身的依賴發(fā)生了改變;

推薦啟用 eslint-plugin-react-hooks 中的 exhaustive-deps 規(guī)則价匠,此規(guī)則會在添加錯誤依賴時發(fā)出警告并給出修復建議 当纱;

7、一些重點

(1)可以把 useEffect Hook 看做 componentDidMount踩窖,componentDidUpdate和 componentWillUnmount這三個函數(shù)的組合坡氯; (2)在 React 的 class 組件中,render 函數(shù)是不應該有任何副作用的洋腮; 一般來說箫柳,在這里執(zhí)行操作太早了,我們基本上都希望在 React 更新 DOM 之后才執(zhí)行我們的操作啥供。

三悯恍、useContext

用來處理多層級傳遞數(shù)據(jù)的方式,在以前組件樹中伙狐,跨層級祖先組件想要給孫子組件傳遞數(shù)據(jù)的時候涮毫,除了一層層 props 往下透傳之外,我們還可以使用 React Context API 來幫我們做這件事贷屎。使用例子如下所示 (1)使用 React Context API窒百,在組件外部建立一個 Context

(2)使用 Context.Provider提供了一個 Context 對象,這個對象可以被子組件共享

(3)useContext()鉤子函數(shù)用來引入 Context 對象豫尽,并且獲取到它的值

四篙梢、useReducer

1、基礎用法

比 useState 更適用的場景:例如 state 邏輯處理較復雜且包含多個子值美旧,或者下一個 state 依賴于之前的 state 等渤滞;例子如下所示

2贬墩、惰性初始化 state

五、Memo

如下所示妄呕,當父組件重新渲染時陶舞,子組件也會重新渲染,即使子組件的 props 和 state 都沒有改變

改進:我們可以使用 memo 包一層绪励,就能解決上面的問題肿孵;但是僅僅解決父組件沒有傳參給子組件的情況以及父組件傳簡單類型的參數(shù)給子組件的情況(例如 string、number疏魏、boolean等)停做;如果有傳復雜屬性應該使用 useCallback(回調(diào)事件)或者 useMemo(復雜屬性)

六、useMemo

假設以下場景大莫,父組件在調(diào)用子組件時傳遞 info 對象屬性蛉腌,點擊父組件按鈕時,發(fā)現(xiàn)控制臺會打印出子組件被渲染的信息只厘。

分析原因:

點擊父組件按鈕烙丛,觸發(fā)父組件重新渲染;

父組件渲染羔味,const info = { name, age } 一行會重新生成一個新對象河咽,導致傳遞給子組件的 info 屬性值變化,進而導致子組件重新渲染赋元。

解決:

使用 useMemo 將對象屬性包一層库北,useMemo 有兩個參數(shù):

第一個參數(shù)是個函數(shù),返回的對象指向同一個引用们陆,不會創(chuàng)建新對象寒瓦;

第二個參數(shù)是個數(shù)組,只有數(shù)組中的變量改變時坪仇,第一個參數(shù)的函數(shù)才會返回一個新的對象杂腰。

七 、useCallback

接著第六章節(jié)的例子椅文,假設需要將事件傳給子組件喂很,如下所示,當點擊父組件按鈕時皆刺,發(fā)現(xiàn)控制臺會打印出子組件被渲染的信息少辣,說明子組件又被重新渲染了。

分析下原因:

點擊父組件按鈕羡蛾,改變了父組件中 count 變量值(父組件的 state 值)漓帅,進而導致父組件重新渲染;

父組件重新渲染時,會重新創(chuàng)建 changeName 函數(shù)忙干,即傳給子組件的 changeName 屬性發(fā)生了變化器予,導致子組件渲染;

解決:?修改父組件的 changeName 方法捐迫,用 useCallback 鉤子函數(shù)包裹一層乾翔, useCallback 參數(shù)與 useMemo 類似

八、useRef

以下分別介紹 useRef 的兩個使用場景:

1施戴、指向 dom 元素

如下所示反浓,使用 useRef 創(chuàng)建的變量指向一個 input 元素,并在頁面渲染后使 input 聚焦

2赞哗、存放變量

useRef 在 react hook 中的作用, 正如官網(wǎng)說的, 它像一個變量, 類似于 this , 它就像一個盒子, 你可以存放任何東西. createRef 每次渲染都會返回一個新的引用雷则,而 useRef 每次都會返回相同的引用,如下例子所示:

九懈玻、useImperativeHandle

使用場景:通過 ref 獲取到的是整個 dom 節(jié)點巧婶,通過 useImperativeHandle 可以控制只暴露一部分方法和屬性乾颁,而不是整個 dom 節(jié)點涂乌。

十、useLayoutEffect

其函數(shù)簽名與 useEffect 相同英岭,但它會在所有的 DOM 變更之后同步調(diào)用 effect湾盒,這里不再舉例。

useLayoutEffect 和平常寫的 Class 組件的 componentDidMount 和 componentDidUpdate 同時執(zhí)行诅妹;

useEffect 會在本次更新完成后罚勾,也就是第 1 點的方法執(zhí)行完成后,再開啟一次任務調(diào)度吭狡,在下次任務調(diào)度中執(zhí)行 useEffect尖殃;

結尾 需要這些資料,可以 關注公眾號? 清風酔? 領取

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末划煮,一起剝皮案震驚了整個濱河市送丰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弛秋,老刑警劉巖器躏,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蟹略,居然都是意外死亡登失,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門挖炬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來揽浙,“玉大人,你說我怎么就攤上這事∧笃迹” “怎么了太抓?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長令杈。 經(jīng)常有香客問我走敌,道長,這世上最難降的妖魔是什么逗噩? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任掉丽,我火速辦了婚禮,結果婚禮上异雁,老公的妹妹穿的比我還像新娘捶障。我一直安慰自己,他們只是感情好纲刀,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布项炼。 她就那樣靜靜地躺著,像睡著了一般示绊。 火紅的嫁衣襯著肌膚如雪锭部。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天面褐,我揣著相機與錄音拌禾,去河邊找鬼。 笑死展哭,一個胖子當著我的面吹牛湃窍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播匪傍,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼您市,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了役衡?” 一聲冷哼從身側響起茵休,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎映挂,沒想到半個月后泽篮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡柑船,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年帽撑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞍时。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡亏拉,死狀恐怖扣蜻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情及塘,我是刑警寧澤莽使,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站笙僚,受9級特大地震影響芳肌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肋层,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一亿笤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧栋猖,春花似錦净薛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至雌团,卻和暖如春燃领,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辱姨。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工柿菩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留戚嗅,地道東北人雨涛。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像懦胞,于是被迫代替她去往敵國和親替久。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 前言 本文全面介紹了React Hooks的所有API概念躏尉、用法蚯根、豐富的demo以及部分底層原理。 實際上胀糜,Rea...
    南宮__閱讀 3,560評論 0 6
  • react rendering原理 舉個栗子 以上程序颅拦,react是這樣渲染的。 每一次渲染中教藻,count的值是固...
    初漾流影閱讀 2,269評論 0 2
  • useState 使用狀態(tài) const [n, setN] = React.useState(0)const [u...
    改革路上最靚的崽閱讀 2,561評論 3 2
  • 前言 最近的換寫React項目了距帅,好久沒有寫React,還動不動就想class??括堤,現(xiàn)在跟上時代碌秸,重新學習React...
    alex夏夜閱讀 1,971評論 1 3
  • 使用React Hooks有什么優(yōu)勢绍移? 什么是hookshook 是一些可以讓你在函數(shù)組件里面鉤入react st...
    Lyan_2ab3閱讀 347評論 0 1