React hooks 讓我相信一見鍾情

sh1zuku
5 min readFeb 5, 2019

--

React hooks 在兩個禮拜前正式啟用了!詳見 PR
想試試的話可以使用 React v16.8.0-alpha.1

Class vs hooks from https://twitter.com/prchdk/status/1056960391543062528

很多人對 React 的印象是學習曲線高、各種生命週期、難以入門,或是已經開始使用 React 但還沒有接觸 hooks,覺得要學的東西已經夠多了,現在又多了新東西該怎麼辦。

不要擔心,直接從 hooks 開始吧!

自從有了 hooks ,Function component 能夠完美取代原本的 Class component,讓程式碼可讀性更高,更有彈性,最重要的是,我認為 hooks 比原本寫法更易上手,也減少了產生 bug 機會,不過完整理解 React component life cycle 還是必須的,經歷過週期的痛,才更能感受到 hook 的美好,就趕緊切入正題吧~

React Hooks 介紹

捨棄了以往的 class,hook 只能在 function component 內使用,且一般會以 use 開頭來識別,基礎的 hook 有兩種:useStateuseEffect,簡單而言就是 component state 和週期間的各種操作 (副作用)。

讓我們看看這個計數器

轉換為 hook 寫法後:

以上兩份程式碼是等價的,只是下圖的 count 被抽離出來,還自帶一個 setCount,以往 function component 被稱為 stateless component,現在也變得 stateful 囉!

更多的 State

上方示範了如何使用多個 state,看看參數會發現 state 內可以放入物件、陣列等等,這意味著可以把 state 細拆成好多個 useState,也可以比照以往,全部放在同一個 state 裡面。

要注意的是 useState 的 setter 會完全取代當前的 state,不同於 class component 中的 setState 是取代 property。

回到剛剛的計數器,並加入一點副作用

useEffect 出場了!以這個範例來說,它的功能是每次 render 時執行一次useEffect 裡頭的 function,且每次 rerender 時都會替換掉 useEffect 內部的 function 並執行,所以每次點擊 button 時除了網頁內容更新外,瀏覽器上方的 title 也會被置換為最新的 count。

以週期來說就相當於在 componentDidMountcomponentDidUpdate 時替換 title,那其他週期呢?

這次是需要手速的計數器

minus function 內的 setCount 必須使用 callback function,為什麼?

看看下方的 useEffect,裡面先是宣告了一個 timer,每 150 毫秒都會讓 count 減少,之後回傳了一個 function,可以看出它的功能是清除 timer。

useEffect 內的 function 可以回傳一個 cleanup function,React 保證每次執行 effect 或是 component unmount 前會執行 cleanup,這樣就不怕 timer 在 unmount 後還繼續執行造成錯誤。

但下方的 useEffect 怎麼多了一個參數?

每次 component update 時 React 會比較這個參數,若與前一次相等 effect 就不會執行,空陣列就意味著只會執行一次 ( 永遠相等 ),以週期來說就相當於只在 componentDidMount 時執行一次 effect,componentWillUnmount 時執行 cleanup,符合想要達到的效果。

手速計數器實際跑起來的樣子(手好痠

可以和 class component 版本比較看看。

後話

身為 React 開發者,接觸 hooks 之後真是相當驚艷,馬上就變得愛不釋手,希望此篇文章能夠提供尚未接觸 hooks 甚至是 React 的開發者一個切入點,一起體驗 hooks 的美好,雖然 hooks 算是較新的 feature,近期較難在 production 中看到,但各種好用的 custom hooks 已如雨後春筍般冒出,我相信 hooks 將會成為潮流。

若想繼續深入 React hooks,請務必看看作者本人的文章以及官網介紹。

感謝您的閱讀,喜歡此篇文章或是有幫助到您的話請幫我鼓鼓掌:)
若有任何問題十分歡迎提問,謝謝。

--

--