1. 程式人生 > >使用 React hooks 轉化 class 的一些思考

使用 React hooks 轉化 class 的一些思考

Hooks 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。

使用 React hooks 轉化 class 的一些思考

  Hooks 其實已經是大勢所趨的一個技術了,作為一個可能是 React,甚至是 JS 史上都是一個比較偉大的發明,Hooks 已經被大部分中小型公司所接受並嘗試使用,但是對於大中型公司來講,從 class 元件移植 Hooks 的成本太高,不能像其他公司一樣隨心所欲地擁抱新技術,所以我們對於 Hooks 的討論,應該考慮的比較全面,才能更好的瞭解這個技術,以及是否應該在專案中嘗試這一新技術。

  在論壇上我也有和一個小夥伴對此有一個討論,感謝@無怨,前代 react 專案 class 轉 hooks 的必要性。其實大家對 hook 都是認可的,但是對於重寫 class 的成本方面還是望而卻步的,react 官方也不希望因為這個使得新版本使用者劇減,所以暫時還是會相容 class 元件的寫法。

  所以其實對於是重寫部分還是隻有新元件使用 hook,大家都還是比較猶豫的,對這種選擇來看,我們必須實際考慮成本-產出比,所以我們這篇就具體討論成本與產出,以及可行的方案吧~

首先咱們來看看成本吧

修改成本

  作為 React 16.8 新增特性,一些第三方的庫可能還暫時無法相容 Hooks,比如 React Redux 從 v7.1.0 才開始支援 Hook API 並暴露了 useDispatch 和 useSelector 等,而 React Router 從 v5.1 開始支援 hooks。所以如果我們的專案中 Redux 和 Router 版本不夠的話,可能需要評價是否有必要升級和升級後可能帶來的問題。

  再一點,業務邏輯內的程式碼拆分。在 hooks 中,是不太建議將 state 放置於同一個 state 中的,考慮到效能及區域更新機制,既 state 切分成多個 state 變數,每個變數包含的不同值會在同時發生變化。建議是將 state 根據業務邏輯,拆分成多個 useState。

  這樣雖然會增加元件的效能,畢竟每次更新都只是更新一部分元件,但是對於重寫 class,我們還需要深入每一個的 class,探究裡面 state 的聯絡、機制等等,是一個較大的阻礙與挑戰。

  還有一點,暫時的話,hooks 必須傳遞 Props 的方式獲取根元件 App 中的 state,意思就是如果想使用主 reducer 庫中的 state 的話,必須使用 props 傳遞進來(或通過把 state 也裝進 Context 來解決,但是空間成本太大了),只有改變其值才可以 dispatch 來修改

  修改成本可以算成本中最大的一環了,事實上每個 class 元件都可能有非常多的邏輯、狀態,各種狀態可能都有內在的一些聯絡。重新去理解這部分程式碼並重新構建 hooks,其實是一件非常大的挑戰,所以本身我暫時對重寫 class 到 hooks 是持觀望態度,當 React 官方沒有一定的苗頭出來說不支援 class 寫法前,重寫的動力確實是不夠充足。

學習成本

  hook 本身其實和 class 一樣,都是關於本身這個元件的實現細節,重不重寫其實對書寫正常業務是完全沒有影響的(不考慮效能方面的話)。所以 hooks 對於 class 的重寫還是會有一定的學習成本在內,畢竟這邊要考慮本身與日後入職的小夥伴對這塊的熟練度。

時間成本

  按我的預估,對一個完整專案中,class 元件轉 hooks,以及部分檔案結構整理的時間可能要一個多月(以我的微薄水平),使用者看不見明顯的功能、UI 修改,不得不說這部分的時間支出是比較大的。

  而如果是原 class 保留不動,新元件使用 hooks 的話,時間成本其實就減少很多了,畢竟新的元件也是從無到有搭建起來,多花的時間可能基本集中在前期對新增 hooks 的結構整理,以及對 redux 倉庫的有機結合上,當結構完善,有咱們自己的一套書寫模式之後,就可以達到現在書寫 class 元件的速度與體驗了。

我們能夠得到什麼?

OK 我們說完了成本,來看看 Hooks 可以帶給我們什麼?

假設是原 class 元件保留,新建 hooks

  hooks 是一個 React 官方的新特性,Hook 的使用是完全能代替 class 元件的使用,也肯定對其有一個比較大的意義在其中,事實上他們內部原理都是 diff and patch,效能方面差距幾乎是可以忽略不計的,但是我的理解是,hooks 更傾向於函數語言程式設計,class 則更傾向於面向物件程式設計。這是一個大趨勢。

  在新的元件中使用 hooks,其實寫過之後就能體會到為什麼有人說Hooks更騷,class更蠢了。它將所有類似生命週期函式都可以用一個 useEffect 來進行模擬,不會使得自己的邏輯大量分佈在 class 的各個角落,大幅度整合業務邏輯程式碼。

  這是新技術。對沒錯,我認為新技術本身就是一個我們能夠看到的"獲得"。在以前我們也會覺得 Jquery 非常好用,以後都會使用這種方式開發,但是後來出現了 webpack,出現了 React、Vue,我們的程式碼書寫形式又變了。新技術的出現本身就是一種訊號,只要它接受住了大量業務情況的考驗,他的存在就是有某種值得值得去獲取的優點,比如後來的元件化、工程化、解耦合等概念。

假設是重寫 class 元件

  除了上述優點外,其實就沒有過多的其他優點了,只是整個專案的檔案結構會更緊湊,畢竟不用相容 class 寫法與 hooks 寫法,但是對於效能來說,是沒有那種顯著提升的。

額外

  效能方面的差距其實是幾乎可以忽略不計的,但是函數語言程式設計是越來越火起來的思想,同時 Hooks 從誕生開始就一直在致力於增強其效能,討論活躍度也足夠高,所以可預想的未來內,hooks 效能方面應該會有一個比較大的飛躍。所以這方面也應該是一個可參考的獲得。

方案

  說了這麼多,其實我們關於 hooks 的選擇就只有這三個:

  1. 重寫所有 class 元件,轉化為 hooks
  2. 原 class 元件不懂,新元件使用 hooks
  3. 原封不動,新元件依舊使用 class 開發

  每個選擇都是有各自的考慮的,比如第一個選擇考慮的是成本較高,第三個選擇是想保持穩定以及開發時間。

  建議假如是新專案或剛剛起步,就全篇使用 hooks 開發(第二種方案),如果已經是穩定上線的專案的迭代,就可以在迭代的元件中使用 hooks,但是如果你的團隊需要考慮學習時間成本,本身開發時間較緊張,那麼還是建議依舊使用 class 元件進行接下來的開發,因為 class 已經很久了,你的團隊一定已經有了一套比較完備的方案與流程來進行接下來的開發,它會讓你節省不少的時間。

本文使用 mdnice 排版