[譯] React Hook 介紹 — React 系列教程 Part 1

LeviDing發表於2018-11-08

Hook 介紹

Hook 是一項新的功能提案,可以讓你在不編寫類的情況下使用狀態(state)和其他 React 功能。它們目前處於 React v16.7.0-alpha 階段,並且在開放式 RFC 中進行著討論。

import { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
複製程式碼

這個 useState 新功能將是我們學習的第一個“鉤子”,但這個例子僅僅是個預告。即便你對它沒感覺也不用擔心!

你可以在下一頁開始學習 Hook。在本頁面上,我們將繼續解釋為什麼我們要將 Hook 新增到 React 中,以及它們如何幫助你編寫出色的應用。

沒有重大的變化

在我們繼續之前,請注意 Hook 是:

  • 完全可選擇引入。 你無需重寫任何現有程式碼,就能在一些元件裡嘗試使用 Hook。但如果你不想,你不必現在學習或使用 Hook。
  • 100% 向後相容。 Hook 不包含任何重大的更改。
  • 現在可用。 Hook 目前處於 alpha 版本,我們希望在收到社群反饋後把它們包含在 React 16.7 中。

沒有把類從 React 中移除的計劃。 你可以在本頁面底部閱讀更多關於漸進式採用 Hook 的策略資訊。

Hook 不會取代你對 React 概念的理解。 相反地,Hook 為你已知的 React 概念(props、state、context、refs 和 lifecycle)提供了更直接的 API。並且稍後我們還將演示,Hook 還提供了一種組合它們新的強大的方式。

如果你只是想開始學習 Hook,請隨意直接跳到下一頁! 你也可以繼續閱讀本頁,詳細瞭解我們為什麼要新增 Hook,以及我們是如何在不重寫應用程式的情況下開始使用它們的。

動機

Hook 解決了我們在過去五年時間裡編寫和維護數以萬計 React 元件時遇到的各種看似不相關的問題。無論你是在學習 React,還是日常使用,甚至說是喜歡使用具有類似元件模型的其他庫,你都有可能注意到這些問題。

在元件之間重用帶狀態邏輯很困難

React 沒有提供把可重用行為“附加”到元件上的方法(例如,把它關聯到 store 裡)。如果你已經使用了 React 一段時間,你可能會熟練使用渲染屬性高階元件的模式嘗試解決這個問題。但這些模式需要你在使用它們的時候對元件進行重構,這可能會很麻煩並且使程式碼更難以跟蹤。如果你看一下 React DevTools 裡的典型 React 應用程式,你也許會發現一個由提供者、消費者、高階元件、渲染屬性和其他抽象層包裹起來的“包裝地獄”元件。雖然我們可以在 React DevTools 中過濾它們,但這裡引出了一個更深層次的基本問題:React 需要一個更好的分享帶狀態邏輯的原語。

使用 Hook,你可以從一個元件中匯出帶狀態邏輯,以便它可以單獨測試和複用。Hook 允許你在不改變元件層次結構的情況下複用帶狀態邏輯。 這樣就可以輕鬆地在多個元件之間或者社群裡共享 Hook。

我們將在編寫自定義鉤子裡進行更多的討論。

複雜的元件變得難以理解

我們經常不得不維護從簡單開始,但後來變成混雜著帶狀態邏輯和副作用無法管理的元件。每個生命週期方法通常都包含了一堆不相關的邏輯。例如,元件也許要在 componentDidMountcomponentDidUpdate 方法裡請求資料。但是,同樣是在 componentDidMount 方法,可能會包含不相關的設定事件監聽的邏輯,還得在 componentWillUnmount 裡清除。本該一起更改的相關聯程式碼被拆分,而完全不相關的程式碼卻最終組合到一個方法裡。這就太容易引入 bug 和導致不一致了。

很多情況下不可能把這些元件拆分得更小,因為到處都有帶狀態的邏輯。而且測試它們也很困難。這就是許多人更喜歡將 React 與單獨的狀態管理庫相結合的原因之一。但是,這通常會引入太多的抽象(概念),使得你在不同的檔案之間跳轉,同時讓重用元件變得更加困難。

為了解決這個問題,Hook 允許你基於相關聯的部分(例如設定訂閱或獲取資料)把一個元件拆分成較小的函式,而不是基於生命週期函式強制拆分。你還可以選擇使用 reducer 管理元件的本地狀態,以使其更具可預測性。

我們將在使用效果 Hook 裡更多地討論這個問題。

類(Class)混淆了人類和機器

通過我們的觀察,發現類是學習 React 最大的障礙。你必須理解 this 在 JavaScript 中是怎麼工作的,大多數語言中它的工作方式有很大不同。你必須記住繫結事件處理程式。如果沒有不穩定的語法提案,程式碼就非常冗長。人們可以很好地理解屬性,狀態和自上而下的資料流,但仍然很艱難地與類作鬥爭。React 中的函式和類元件之間的區別以及何時使用哪種元件,即使在經驗豐富的 React 開發人員之間也會引發分歧。

此外,React 已經推出大概五年時間了,並且我們希望確保它在未來的五年裡還保持相關性。就像 SvelteAngularGlimmer 和其他人表明的那樣,提前編譯元件未來有很大的潛力。特別是在它不侷限於模版的情況下。目前,我們已經使用 Prepack 做了元件摺疊的實驗,並且我們已經看到了有前景的早期結果。但是,我們發現類元件可能會引發無意識的模式使得這些優化回退到較慢的路徑上。類也給今天的工具提出了問題。例如,類不能很好地壓縮,並且它們使得熱更新載入變得片狀和不可靠。我們希望提供一種 API,使程式碼更可能的留在可優化的路徑上。

為了解決這個問題,Hook 允許你在沒有類的情況下使用更多 React 的功能。 概念上來說,React 元件一直是更接近於函式的。Hook 擁抱函式,但不會犧牲掉 React 實際的精神。Hook 提供了對命令式逃生艙口的訪問,並且不需要你學習複雜的函式式或反應式程式設計技術。

例子

Hook 概覽是開始學習 Hook 的好地方。

逐步採用策略

TLDR:沒有從 React 中移除類的計劃

我們知道 React 開發者專注於釋出產品,沒有時間研究正在釋出的每個新 API。Hook 是很新的,在考慮學習或採用它們之前等待更多的示例和教程可能會更好。

我們也理解為 React 新增新原語的標準非常高。對於好奇的讀者來說,我們已經事先準備了一個詳細的 RFC,裡面有更多深入細節的動機,並提供有關特定設計決策的額外視角和相關領先技術。

至關重要的是,Hook 和現有程式碼是並行工作的,所以你可以逐步採用它們。 我們正在分享這個實驗性的 API,為了是從社群中那些有興趣塑造 React 未來的人那裡得到早期反饋 —— 然後我們會在公開場合迭代 Hook。

最後,別急著遷移到 Hook。我們建議避免任何“重大改寫”,特別是對於現有複雜的類元件。開始“考慮 Hook”需要一點心理上的轉變。根據我們的經驗,最好先在新的和非相關的元件裡練習使用 Hook,並確保團隊中的每個人都對它們感到滿意。在你嘗試 Hook 之後,請隨時給我們傳送反饋,無論是積極的還是消極的。

我們打算讓 Hook 能覆蓋所有現有的類用例,但我們將在可預見的未來繼續支援類元件。 在 Facebook,我們有數以萬計用類編寫的元件,顯然我們沒有要重寫它們的計劃。相反地,我們開始在新的程式碼中並行使用 Hook 和類。

下一步

在本頁的末尾,你應該大致瞭解 Hook 正在解決的問題,但很多細節可能還不清楚。別擔心!現在讓我們進入下一頁,我們通過示例開始學習 Hook。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章