React 學習筆記 3 — 聊聊元件的生命週期與 Hooks

Sean Chou
Recording everything
8 min readJul 18, 2021

--

from: unsplash

在能夠建立起一個簡單的 React Todo List 與初步了解了 state 與 props 之後,為了能再稍微了解 React 一點點,元件的生命週期與 Hooks 也是在 React 開發中最基本需要知道的知識之一,這篇筆記主要紀錄跟 React 元件相關的學習,順便也讓自己再重新複習一下。

前情提要:

Class Component & Function Component

在 React 中的 component 有兩種宣告方式,一種是使用單純的 function,一種是使用 JavaScript ES6 的 Class 的方式來宣告。

兩者產生出來的 component 實際功能上沒有太大差異,class component 沒有辦法很好的壓縮,所以產出來的 code 會比較多,以及在 react v16.8 之前, function component 是不能有任何狀態的,只是單純的把內容 render 出來。而後來出現的 hooks 就是一種讓 function component 能夠使用狀態的方式,至於什麼是 hooks ,等等再回來聊。

來看看加上狀態之後的兩種 component 寫法會變成什麼樣子:

  • Function component: 直接使用 useStatehooks來宣告狀態
  • Class component: 在 constructor 中做初始設置 this.state

實務上在工作的開發,目前已經幾乎都使用 function component 搭配 Hooks 來使用了,不僅寫法簡潔,也比較不會因為錯誤的操控生命週期的方法而造成不預期的 bug。

生命週期

渲染在畫面上的元素,他的生命週期可以有三個階段:

Mount -> Update -> Unmount

  • Mount: 元件被渲染到畫面上
  • Update: 元件的內容因為資料的更動而重新渲染
  • Unmount: 元件從畫面上消失,移除這個元件

如果視覺化 Lifecycle 的過程,可以看看以下這張圖:

from: https://github.com/wojtekmaj/react-lifecycle-methods-diagram

Mounting

constructor

在元件一開始 mount 的時候,初始化會先經過建構子 constructor,相信這個在有物件導向程式基礎的人應該都很熟悉,constructor 會做完所有必要的 initial 過程。

render

接著就會進入 render 的程序,在 class component 中會去跑 render() 這個 function,而 function component 則是最後的 return function。

componentDidMount

最後會到 componentDidMount 的這個狀態,也就是這個 component 已經渲染完成的狀態。在這個狀態下你可以去做其他的商業邏輯,比如說這時候去呼叫後端的 API 拿相對應的資料,根據資料再去判斷需不需要重新更新渲染。

Updating

trigger update

在元件收到資料更新的時候,就會觸發 update,可能是父元件傳進來的 props 更新,或是自己內部的 state 因為使用者的操作而更新。

render

更新的時候一樣會再次觸發 render 這個過程,根據最新的資料來渲染元件,React 自己有一套 Virtual Dom 的比對方式,能夠在更新的時候只去做最小程度的渲染,以增加整體的效率。

componentDidUpdate

元件更新完成後,就會到 componentDidUpdate 的這個狀態。在這狀態下假如你去更新 state ,就會到一個一直更新的無限迴圈,然後你的瀏覽器就會準備當掉,大概是一個剛開始學習 react 會踩到的一個小坑。

Unmounting

當元件要被從畫面移除的時候,則會進入這個狀態,在這狀態下通常可以去清理一些 timer 之類的設定。

以上就是簡單的元件生命週期,理解生命週期在對於開發上是非常必要且很有幫助的,以下為比較詳細的 Lifecycle 圖可以參考:

from: twitter @dan_abramov

Hooks

在使用 class component 的時候,不夠經驗豐富的開發者,在各種 lifecycle 的方法混用下,很容易產生了各種很難維護的 component 與隱藏的 bug。另外,在 class component 的時候也很難將狀態相關的邏輯很好的共用,而 Hooks 出現後,可以自定義 Custom Hooks 來做到這件事。

Hooks 是為了讓撰寫 React component 的時候可以更簡潔、更簡單,也透過 effect的使用,來減少了以往各種 lifecycle 狀態複雜的使用,不但讓程式碼可讀性更高,更有彈性,也間接降低了一些進入門檻。

Hooks 的公開出現介紹是在 React Conf 2018 上,有興趣的話可以看看當時的影片:

以開發上最常使用的應該就是 state hook 和 effect hook 了。

State Hook

以往要把 component 變成一個 stateful component,必需要使用 class component 來宣告這個元件,而 hooks 當中的 useState 就是一個讓你增加 React state 到 function component 的 Hook。

他的概念在上一篇舊紀錄過了,這裡拿上一篇用的範例來簡單描述一下

簡單來說, useState() 會回傳兩個值,第一個是當前的狀態,第二個是一個 function,用來改變這個狀態的 set function。

  • count: 這就是存活在 component 之中的狀態
  • setCount: 用來更新這個狀態的方法,要更新的時候就是 setCount(2)
  • useState(0): 當中的 0,代表是預設值

在 component,可以直接使用 count 來做邏輯判斷或是直接渲染到畫面上,而 setCount() 可以用來在 user 按下 add count button 的時候,去更新這個存活在 component 之中的狀態 count

每次 component 渲染的時候,都是去看當下的 state 是什麼,而相對應的去渲染當下的 state,並不是任何的 data binding 的概念。

以下就是官方文件上完整的例子:

Effect Hook

Effect hook 的意思為在 component 的單一資料流下,加上會影響的 side effects (副作用)操作,可能是跟後端 API 要資料,也可能是去對 props 的資料做修改(非直接修改)。他對照到先前 class component,就如同把 componentDidMount, componentDidUpdatecomponentWillUnmount 整合起來。

useEffect 的參數是一個 function,會在 React 更新完 DOM 之後執行這個 function,拿剛剛的 Counter 例子來看,如果想要再每次 state 更新後,我們都去改瀏覽器 tab 上面的文字,可以加入 effect hook:

可以看到在每次 render 結束的時候,會觸發 useEffect ,這時候就會呼叫裡面的這個 function ,達到更改 title 的行為。

以上就是最基本的用法,當然在實務上只理解這些是不太夠的,大概只能寫簡單的 todo list 吧,如果想更深入了解 effect hook ,網路上這篇內容覺得寫得蠻好也比較進階,可以參考:

延伸閱讀:

--

--