React Hooks 已經出現好一陣子了,現在初學 React 的新手,可能都已經用 hook 用得很順手了。
但如果接手到比較舊一點的 React 專案,可能還會看到以 Class 為主體的 component,那 Class 與 functional component 差在哪裡呢?為什麼現在都直接無腦使用 React hook 了呢?
React 是一個元件導向的 view library,在 v16.8 之前一直都是用 Class 來組織元件,然後用一個個元件排列組合,組成元件樹,完成期待的畫面呈現。
而在元件與元件之間的溝通,往往也可以透過單純的父子 props 傳遞,或者 HOC (higher-order components)、context 等方式。
同時,Class 元件自身也可以擁有自己的 state,也就是 this.state
,達成簡易的封裝與狀態管理的功能。
聽起來 Class component 已經夠棒了,然而 Redux 的作者 Dan Abramov 提到:
However, we often can’t break complex components down any further because the logic is stateful and can’t be extracted to a function or another component.
componentDidUpdate
裡面的那種),但很難被拉出來共用通常要共用會採用 HOC,也就是會看到類似這種東西:
withAuth(withRouter(withUserStatus(UserDetail)))
除了可讀性的問題以外,這樣層層傳遞的 props,真正到達要使用的層級時,也可能發生 props 丟失或不如預期的結果,這一切問題的矛頭都指向 「階層架構」與「共用」。
Hook 是 React v16.8 中增加的新功能,就像「鉤子」一樣,可以「鉤」在 function-base 的 component 上,不必寫 Class 就能使用 state 以及其他 React 的功能。
因此,一些基本的內建 hook:
useState
用來代替 Class 裡面用到的 this.state
useEffect
用來代替 Class 裡面的生命週期 componentDidMount
、componentDidUpdate
、componentWillUnmount
useMemo
用來代替 Class 裡面的 shouldComponentUpdate
甚至,因為 hook 的本質就是 function,所以也可以寫自定義的 hook,感覺其實就像自己定義一個 function 一樣。
就是這關鍵的功能,解決了上述提到的問題,成功把需要共用的商業或 UI 邏輯,包成一個共用的 hook(可以想像成共用的 function),使用起來也像在 call function 一樣。
而重點是,使用 hook 無關乎階層架構的問題,就跟 function 一樣想怎麼用就怎麼用,讓維護程式碼的難度下降不少。
不過 hook 畢竟還是跟一般的 function 不一樣,它有一些使用規則:
React 使用這些規則來保證每次 render 時,呼叫 hook 的順序都是一樣的。
官網的解說可以參考這篇,以及這篇,大致上是因為,每一個 component 有一個「memory cell」的內部列表,而這個列表需要根據 index 來找到對應的值,當我們呼叫 useState 這種 hook 的時候,會按照 hook 的順序到列表取得對應的 local state,因此如果 hook 沒有按照順序,就會導致取到錯誤的值。
useSelector
就取代了 connect
和 mapStateToProps
componentDidMount
、componentDidUpdate
、componentWillUnmount
)的功能,如果沒用好反而會出現意料之外的 bug上述提到的缺點其實也不是太嚴重,比如 useEffect 只要遵循單一職責原則,一個 useEffect 只做一件事,並且正確理解第二個參數 dependency array,其實也不用太擔心。
React hook 的出現,最主要的目的仍在於「拆分」,不管要拆的是重複的元件還是純商業邏輯,只要盡可能讓粒度最小化,各功能職責單一,這樣不僅容易組裝,也方便測試。
由於我初次學習 React 的時間點,剛好就介於「class component 獨佔」與「hook 要紅起來」之間,一個尷尬的時間點。
當我好不容易搞懂生命週期,能夠正常維護一個 Class component 了,突然半路就殺出一個 hook!從此我又進入 useEffect 以及它的 dependency 迷陣中。
因此我滿能體會轉移到 hook 思維,過程中的學習曲線真的是滿不容易的,甚至可能比從沒學過 react 的人還要難QQ
不過現在兩邊都懂了之後,覺得嗯。。。還是 hook 寫起來快樂一點XD"
React hooks 介紹
Making Sense of React Hooks
知乎 - 談談 React hooks 的優缺點
知乎 - React 為什麼需要 hook