本文引自
https://zh-hans.reactjs.org/docs/hooks-intro.html
Hook 是 React 16.8
的新增特性。它可以讓你在不編寫 class
的情況下使用 state
以及其他的 React
特性连躏。
注意
React 16.8.0 是第一個支持 Hook 的版本剩岳。升級時,請注意更新所有的 package入热,包括 React DOM拍棕。 React Native 從 0.59 版本開始支持 Hook晓铆。
一、Hook沒有破壞性改動
在我們繼續(xù)之前绰播,請記住 Hook 是:
- 完全可選的骄噪。 你無需重寫任何已有代碼就可以在一些組件中嘗試 Hook。但是如果你不想蠢箩,你不必現(xiàn)在就去學(xué)習(xí)或使用 Hook链蕊。
- 100% 向后兼容的。 Hook 不包含任何破壞性改動滔韵。
- 現(xiàn)在可用掌实。 Hook 已發(fā)布于 v16.8.0。
沒有計劃從 React 中移除 class宴卖。 你可以在本頁底部的章節(jié)讀到更多關(guān)于 Hook 的漸進策略症昏。
Hook 不會影響你對 React 概念的理解拘悦。 恰恰相反,Hook 為已知的 React 概念提供了更直接的 API:props分苇, state医寿,context蘑斧,refs 以及生命周期。稍后我們將看到沟突,Hook 還提供了一種更強大的方式來組合他們惠拭。
如果不想了解添加 Hook 的具體原因,可以直接跳到下一章節(jié)開始學(xué)習(xí) Hook棒呛! 當(dāng)然你也可以繼續(xù)閱讀這一章節(jié)來了解原因域携,并且可以學(xué)習(xí)到如何在不重寫應(yīng)用的情況下使用 Hook。
二趋观、使用Hook的動機
Hook 解決了我們五年來編寫和維護成千上萬的組件時遇到的各種各樣看起來不相關(guān)的問題拆内。無論你正在學(xué)習(xí) React宠默,或每天使用搀矫,或者更愿嘗試另一個和 React 有相似組件模型的框架瓤球,你都可能對這些問題似曾相識敏弃。
問題1:在組件之間復(fù)用狀態(tài)邏輯很難
React 沒有提供將可復(fù)用性行為“附加”到組件的途徑(例如,把組件連接到 store)绿饵。如果你使用過 React 一段時間拟赊,你也許會熟悉一些解決此類問題的方案粹淋,比如 render props 和 高階組件桃移。但是這類方案需要重新組織你的組件結(jié)構(gòu),這可能會很麻煩过吻,使你的代碼難以理解第步。如果你在 React DevTools 中觀察過 React 應(yīng)用缘琅,你會發(fā)現(xiàn)由 providers廓推,consumers,高階組件呻纹,render props 等其他抽象層組成的組件會形成“嵌套地獄”雷酪。盡管我們可以在 DevTools 過濾掉它們涝婉,但這說明了一個更深層次的問題:React 需要為共享狀態(tài)邏輯提供更好的原生途徑。
你可以使用 Hook 從組件中提取狀態(tài)邏輯吩跋,使得這些邏輯可以單獨測試并復(fù)用锌钮。Hook 使你在無需修改組件結(jié)構(gòu)的情況下復(fù)用狀態(tài)邏輯引矩。 這使得在組件間或社區(qū)內(nèi)共享 Hook 變得更便捷旺韭。
具體將在自定義 Hook 中對此展開更多討論。
問題2:復(fù)雜組件變得難以理解
我們經(jīng)常維護一些組件混蔼,組件起初很簡單珊燎,但是逐漸會被狀態(tài)邏輯和副作用充斥悔政。每個生命周期常常包含一些不相關(guān)的邏輯。例如槽地,組件常常在 componentDidMount
和 componentDidUpdate
中獲取數(shù)據(jù)捌蚊。但是,同一個 componentDidMount
中可能也包含很多其它的邏輯挺智,如設(shè)置事件監(jiān)聽窗宦,而之后需在 componentWillUnmount
中清除。相互關(guān)聯(lián)且需要對照修改的代碼被進行了拆分媒怯,而完全不相關(guān)的代碼卻在同一個方法中組合在一起髓窜。如此很容易產(chǎn)生 bug,并且導(dǎo)致邏輯不一致杨拐。
在多數(shù)情況下,不可能將組件拆分為更小的粒度帆阳,因為狀態(tài)邏輯無處不在。這也給測試帶來了一定挑戰(zhàn)山宾。同時资锰,這也是很多人將 React 與狀態(tài)管理庫結(jié)合使用的原因之一阶祭。但是,這往往會引入了很多抽象概念鞭盟,需要你在不同的文件之間來回切換齿诉,使得復(fù)用變得更加困難。
為了解決這個問題歇竟,Hook 將組件中相互關(guān)聯(lián)的部分拆分成更小的函數(shù)(比如設(shè)置訂閱或請求數(shù)據(jù))焕议,而并非強制按照生命周期劃分馋记。你還可以使用 reducer 來管理組件的內(nèi)部狀態(tài),使其更加可預(yù)測宽堆。
我們將在使用 Effect Hook 中對此展開更多討論畜隶。
問題3:難以理解的 class
除了代碼復(fù)用和代碼管理會遇到困難外号胚,我們還發(fā)現(xiàn) class 是學(xué)習(xí) React 的一大屏障猫胁。你必須去理解 JavaScript 中 this
的工作方式,這與其他語言存在巨大差異届惋。還不能忘記綁定事件處理器菠赚。沒有穩(wěn)定的語法提案衡查,這些代碼非常冗余。大家可以很好地理解 props俱饿,state 和自頂向下的數(shù)據(jù)流塌忽,但對 class 卻一籌莫展砚婆。即便在有經(jīng)驗的 React 開發(fā)者之間突勇,對于函數(shù)組件與 class 組件的差異也存在分歧甲馋,甚至還要區(qū)分兩種組件的使用場景迄损。
另外芹敌,React 已經(jīng)發(fā)布五年了,我們希望它能在下一個五年也與時俱進碧聪。就像 Svelte液茎,Angular捆等,Glimmer等其它的庫展示的那樣,組件預(yù)編譯會帶來巨大的潛力谒养。尤其是在它不局限于模板的時候明郭。最近达址,我們一直在使用 Prepack 來試驗 component folding沉唠,也取得了初步成效苛败。但是我們發(fā)現(xiàn)使用 class 組件會無意中鼓勵開發(fā)者使用一些讓優(yōu)化措施無效的方案罢屈。class 也給目前的工具帶來了一些問題。例如锄贷,class 不能很好的壓縮,并且會使熱重載出現(xiàn)不穩(wěn)定的情況柔昼。因此炎辨,我們想提供一個使代碼更易于優(yōu)化的 API。
為了解決這些問題乙嘀,Hook 使你在非 class 的情況下可以使用更多的 React 特性虎谢。 從概念上講低缩,React 組件一直更像是函數(shù)。而 Hook 則擁抱了函數(shù)讳推,同時也沒有犧牲 React 的精神原則银觅。Hook 提供了問題的解決方案坏为,無需學(xué)習(xí)復(fù)雜的函數(shù)式或響應(yīng)式編程技術(shù)。
示例
Hook 概覽是開始學(xué)習(xí) Hook 的不錯選擇洒忧。
三够颠、Hook符合漸進策略
總結(jié):沒有計劃從 React 中移除 class。
大部分 React 開發(fā)者會專注于開發(fā)產(chǎn)品蛉抓,而沒時間關(guān)注每一個新 API 的發(fā)布巷送。Hook 還很新矛辕,也許等到有更多示例和教程后付魔,再考慮學(xué)習(xí)或使用它們也不遲抒抬。
我們也明白向 React 添加新的原生概念的門檻非常高擦剑。我們?yōu)楹闷娴淖x者準(zhǔn)備了詳細的征求意見文檔芥颈,在文檔中用更多細節(jié)深入討論了我們推進這件事的動機爬坑,也在具體設(shè)計決策和相關(guān)先進技術(shù)上提供了額外的視角。
最重要的是售担,Hook 和現(xiàn)有代碼可以同時工作署辉,你可以漸進式地使用他們哭尝。 不用急著遷移到 Hook。我們建議避免任何“大規(guī)模重寫”逝淹,尤其是對于現(xiàn)有的桶唐、復(fù)雜的 class 組件尤泽。開始“用 Hook 的方式思考”前,需要做一些思維上的轉(zhuǎn)變醉蚁。按照我們的經(jīng)驗鬼店,最好先在新的不復(fù)雜的組件中嘗試使用 Hook妇智,并確保團隊中的每一位成員都能適應(yīng)。在你嘗試使用 Hook 后巍棱,歡迎給我們提供反饋航徙,無論好壞。
我們準(zhǔn)備讓 Hook 覆蓋所有 class 組件的使用場景杠袱,但是我們將繼續(xù)為 class 組件提供支持窝稿。在 Facebook伴榔,我們有成千上萬的組件用 class 書寫,我們完全沒有重寫它們的計劃塘安。相反耙旦,我們開始在新的代碼中同時使用 Hook 和 class萝究。