React官方最近提倡大家使用Functional programming來設計React,其中也有提到為什麼要用React hooks的原因以前大家常犯的錯誤有哪些,以下就來針對這些情境來探討。

React的side effect介紹

談到React的side effect,最具有代表性的就是:

  1. componentDidUpdate
  2. useEffect

介紹

最近剛入手React的人可能對useEffect比較熟悉,而已經使用一段時間的人,大概都認識componentDidUpdate(而且也被它折騰了好一陣子了)此外,React官方目前統稱在React中effect都稱為side effect,所以當我們在使用side effect這個名詞時,需要稱為定位一下他的意思。

兩者差異

最大的差異就是在React 16.8版本之後,React hooks系列才正式使用,也是React開始提倡全面使用functional component的開始。componentDidUpdate則是以前class based component的產物。

  1. componentDidUpdate
    當Virtual-DOM render完之後,若props或state改變,componentDidUpdate life cycle將會執行你的動作。
    聽起來可能很單純,但是componentDidUpdate的撰寫很常成為大家的夢魘,因為你要知道你寫這段程式在componentDidUpdate前後的狀況會是什麼。
    經典的例子就是,如果你在componentDidUpdate裡面撰寫this.setState是一件很危險的事情,因為一旦你改變了state,會再觸發一次life cycle,如果邏輯寫得不好,你會發現你寫出了一段死循環的render而crash整個component。
    這也是為什麼React希望藉由hooks改善這些比較tricky的問題,對沒有實戰經驗的新手來說,是一個很大且不容易解的門檻。

  2. useEffect
    React hooks之所以叫hooks也是因為它具有鉤子的概念,例如useEffect可以想像成是勾住特定的資料,只要勾住的資料有變動,就會觸發特定的事件。

主要的問題點

  1. 重複的程式
    React官方注意到一個問題,照理來說我們是要在render之後就要執行mount上之後的動作,無論是剛render完還是render完之後,我們可能會判斷類似情境的動作來render,因此會時常寫出重複邏輯的程式在componentDidMount和componentDidUpdate上面。

  2. 萬惡的componentDidUpdate
    當有資料更新要render的時候,我們時常第一個想到的就是componentDidUpdate,但是這個處理得不好,很容易寫出dirty code與有bug的程式。這在上面已經提到了。

補充

其實componentDidUpdate在某些情境下,不一定需要撰寫,可以用functional programming的方式去改善它,在之後的文章會來介紹這部分。

useEffect改善了什麼

  1. 概念簡單
    useEffect的邏輯很簡單,只要勾住特定的資料改變,就執行特定的邏輯。

  2. 可以取代三種life cycle
    useEffect可以當作componentDidMount, componentDidUpdate和componentWillUnmount使用。
    什麼?怎麼這麼神?就是這麼神,開發者只要記住一種功能的三種用法,而不是記三種功能的三種方法了,提升了開發者體驗。

componentDidMount

第二個parameter寫成空陣列表示在一開始render後,只會執行一次。

1
2
3
useEffect(() => {
// ...
}, []);

componentDidUpdate

將要觸發的變數寫在第二個parameter的陣列內。

1
2
3
useEffect(() => {
// ...
}, [triggerA, triggerB, ...]);

componentWillUnmount

當component要unmount的時候,會執行return內的程式。

1
2
3
4
useEffect(() => {
// ...
return () => {...};
}, [triggerA, triggerB, ...]);
  1. 分離成多個side effects
    以前可能會把多種會發生side effect的邏輯寫在同一個componentDidUpdate裡面,但是現在呢,你可以寫成多個useEffect,一方面讓你的開發邏輯清楚,另一方面你也很好管理你的程式,不容易寫出無法預期的side effects出來(這點很重要)