React hooks useEffect 比較常犯的錯誤

Peace Pan
萬達寵物系統發展部
3 min readJul 26, 2019

React Hooks 是去年 2018 年底 React 16.8 推出的新功能,但目前對於一些開發者而言,還算是處在一個比較新的功能,畢竟目前依然還是可以使用 React 16.8 前的開發方式來撰寫 React

這邊紀錄自己以前剛接觸 React Hooks 時,在開發時寫 useEffect 常常一個恍神或思緒異常時就會犯的錯誤。

1. 想只執行一次時,卻沒有帶入空的 deps

useEffect 的第 2 個參數 deps 是一個可選的陣列參數,當有帶入時,React 即會監聽陣列內輸入的參數。

當參數的 Reference 或 Value 變化時,就會觸發 Effect。但是當沒有輸入時,則代表每一次 Render 都會觸發 Effect。而當 deps 帶入空陣列時,則該 Effect 只會在首次 Render 時執行,如同 componentDidMount

2. 元件 unmount 時,cleanup 函式內直接存取 value

範例程式碼

因為 useEffect 的 clean 函式建構的當下,function 的 scope 已經不同,這會導致存取到的變數永遠都是首次 Render 當下時的變數。有時候程式寫太快都會忘了這個問題。

3. useEffect 裡處理非同步操作後沒有檢查 mounted 狀態就 setState

其實這個情況在任何 React 版本都要預防,這個情況常常發生在抓資料的時候,如果抓完資料後 Component 已經卸載了,這時再 setState 就可能造成該 Component 不會被 GC 回收,而佔用了記憶體然後一直回收不了,記憶體空間就這樣被吃掉了,這對 SPA 來說是很傷的一件事。

只要記得乖乖地用個 useRef 紀錄 mounted 狀態來判斷,或者寫個像 useAsync 來統一處理就好了

結論

總而言之,使用 React Hooks 開發時,很吃重 Javascript 的 Primitive types 與 Object types 的基本概念。

Primitive types are manipulated by value and object types are manipulated by reference.

— 原始型別處理值,物件型別處理參考

[JS基礎:Primitive type v.s Object types]

很清楚 Reference 與 Value 在函式之間傳遞的差異以及熟知 React Component 的生命週期的話,基本上開發時就能大量減少這些犯錯的機會了。

--

--