React Hooks 之 useState 的陷阱
一般來說,正常的 React Component 重新 render 的規則是
只要 State 或是 Props 有改變,一律重繪
這個規則,不管是 Class Component 或是 Functional Component 都是一樣的。
這個主題在 為什麼我的 React Component 畫面不會更新 ? 一文中有提到,但這個問題應該是比較多人在使用 Hooks 上會遇到問題的,所以特別抽出一篇文章重新解釋一次。
為什麼會一律重繪?
原因是 React 的生命週期 shouldComponentUpdate
永遠都是回 true
的關係
什麼是 shouldComponentUpdate?
React Component 的生命週期之一,讓 React Component 知道自己該不該更新。
要如何讓 React Component 某些情況不更新來增加效能?
- 自己實作 Class Component 的
shouldComponentUpdate
(不推薦,通常只會讓程式可讀性降低,與增加造成查問題的困難度) - Class Component 使用 Pure Component
- Functional Component 使用
memo
API
後兩者都是使用 Pure 策略,官方幫你在 shouldComponentUpdate
實作「淺層比較 Shallow Equal」,達到更好的效能。
如果你還不知道什麼是淺層比較 Shallow Equal,請看:Shallow Compare
另外, Pure 策略並不是效能的萬靈藥,請看:React 巢狀 Component 效能優化
useState 有什麼陷阱?
使用 React useState API ,讓我們的 Functional Component 可以有 State 的能力,但我們如果不 實作 memo
API,我們預期應該是要跟 React Class Component 一樣的行為「一律重繪」。
範例
你會發現 State 雖然更新了,但畫面卻沒有改變,為什麼?
因為 Hooks 的 useState 實作
抽絲剝繭,跑去看了 React 原始碼,原因其實出在 useState
的實作,最後會走向 shallow Equal 的方法,「判斷之前的狀態與之後的狀態」來決定是不是要更新 Component,所以其實 useState 自帶 shallowEqual 的比較,請務必特別注意。
- useState 的 shallowEqual 原始碼:https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberHooks.js#L652
Hi 我是 Ryan,如果這篇文章有幫助到你,請你不吝嗇的給予我鼓掌,那將是我進步的動力!👏
另外,你知道 Medium 一篇文章拍手其實可以拍 50 下嗎?如果你願意,請賜我掌聲,謝謝!