探討React的side effects
React官方最近提倡大家使用Functional programming來設計React,其中也有提到為什麼要用React hooks的原因以前大家常犯的錯誤有哪些,以下就來針對這些情境來探討。
React的side effect介紹
談到React的side effect,最具有代表性的就是:
- componentDidUpdate
- useEffect
介紹
最近剛入手React的人可能對useEffect比較熟悉,而已經使用一段時間的人,大概都認識componentDidUpdate(而且也被它折騰了好一陣子了)此外,React官方目前統稱在React中effect都稱為side effect,所以當我們在使用side effect這個名詞時,需要稱為定位一下他的意思。
兩者差異
最大的差異就是在React 16.8版本之後,React hooks系列才正式使用,也是React開始提倡全面使用functional component的開始。componentDidUpdate則是以前class based component的產物。
componentDidUpdate
當Virtual-DOM render完之後,若props或state改變,componentDidUpdate life cycle將會執行你的動作。
聽起來可能很單純,但是componentDidUpdate的撰寫很常成為大家的夢魘,因為你要知道你寫這段程式在componentDidUpdate前後的狀況會是什麼。
經典的例子就是,如果你在componentDidUpdate裡面撰寫this.setState是一件很危險的事情,因為一旦你改變了state,會再觸發一次life cycle,如果邏輯寫得不好,你會發現你寫出了一段死循環的render而crash整個component。
這也是為什麼React希望藉由hooks改善這些比較tricky的問題,對沒有實戰經驗的新手來說,是一個很大且不容易解的門檻。useEffect
React hooks之所以叫hooks也是因為它具有鉤子的概念,例如useEffect可以想像成是勾住特定的資料,只要勾住的資料有變動,就會觸發特定的事件。
主要的問題點
重複的程式
React官方注意到一個問題,照理來說我們是要在render之後就要執行mount上之後的動作,無論是剛render完還是render完之後,我們可能會判斷類似情境的動作來render,因此會時常寫出重複邏輯的程式在componentDidMount和componentDidUpdate上面。萬惡的componentDidUpdate
當有資料更新要render的時候,我們時常第一個想到的就是componentDidUpdate,但是這個處理得不好,很容易寫出dirty code與有bug的程式。這在上面已經提到了。
補充
其實componentDidUpdate在某些情境下,不一定需要撰寫,可以用functional programming的方式去改善它,在之後的文章會來介紹這部分。
useEffect改善了什麼
概念簡單
useEffect的邏輯很簡單,只要勾住特定的資料改變,就執行特定的邏輯。可以取代三種life cycle
useEffect可以當作componentDidMount, componentDidUpdate和componentWillUnmount使用。
什麼?怎麼這麼神?就是這麼神,開發者只要記住一種功能的三種用法,而不是記三種功能的三種方法了,提升了開發者體驗。
componentDidMount
第二個parameter寫成空陣列表示在一開始render後,只會執行一次。
1 | useEffect(() => { |
componentDidUpdate
將要觸發的變數寫在第二個parameter的陣列內。
1 | useEffect(() => { |
componentWillUnmount
當component要unmount的時候,會執行return內的程式。
1 | useEffect(() => { |
- 分離成多個side effects
以前可能會把多種會發生side effect的邏輯寫在同一個componentDidUpdate裡面,但是現在呢,你可以寫成多個useEffect,一方面讓你的開發邏輯清楚,另一方面你也很好管理你的程式,不容易寫出無法預期的side effects出來(這點很重要)