iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
自我挑戰組

我與 React 的 30天系列 第 21

Day 21 不管怎樣都用 React.memo 就好了 ?

  • 分享至 

  • xImage
  •  

前幾天我們都在介紹這些優化 React 效能的好東西,像是 memouseCallbackuseMemo,在我們的組件需要重複渲染時,不會被沒有改變的狀態去影響到我的子組件,進而減少不必要的渲染

所以我們就在 React 專案中全部都加上,memouseCallbackuseMemo,這樣一定可以有效的減少我的重複渲染的問題!

但是真的是這樣嗎? 其實在追求效能的背後都是滿滿的成本

useCallback useMemo 的使用時機

這兩個大家應該會比較好區分

useMemo 通常會用在處理複雜且耗時計算時使用
useCallback 需要傳遞一個 function 給子層,且不會受到父層重新渲染時影響

但是為何在上段結尾會說 追求效能的背後都是滿滿的成本

讓我們來看看如何定義 useCallback 以及 useMemo

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

在使用這兩個

我們必須先去定義 function 以及 一個 dependency Array,在任何的程式語言中只要多一行 code,就會增加執行時的成本,更何況這兩個 Hook 還會幫你記住 記憶體位址,並且去比對前次狀態和現在狀態是否又不同,再去決定是否要渲染畫面

所以除非是需要大量計算,或是畫面不需要常常重新渲染的話,否則可以不用使用到這兩個 HooK

全部的元件都用 memo 就好了?

同理使用 memo 時,React一樣會幫記住 這次渲染的 props 是什麼,並且去做比對上一次 prop 和這次是否有不同,再決定是否渲染

如果我的每個組件都使用 memo,因為 React 需要記住東西太多了,所以可能反而會在初次渲染時變慢

所以我認為我們不該去濫用 memo,我們應該思考的是如何將我們的元件規劃好!

規劃好你的元件,不再被多餘的 re-render

其實這是最理想的狀況,就是設計好元件與元件的關係,盡量不要造成無謂的重複渲染

舉個例子
我們可以看到每當點擊按鈕時 執行 setCount,就會造成整個元件渲染,盡而引響子層渲染,這樣就會操成無謂的渲染

const App = () => {
	const [count, setCount] = useState(0)
	return (
    <>
      <div>
        <button onClick={() => {setCount(perv => perv + 1)}}>+</button>
        { count }
      </div>
      <SlowComponent />
    </>
  )
}

所以我們可以改成這樣,將元件切分的更細,就不會相互引響

const App = () => {
	return (
    <>
      <Counter />
      <SlowComponent />
    </>
  )
}

const Counter = () => {
	const [count, setCount] = useState(0)

	return (
    <div>
      <button onClick={() => {setCount(perv => perv + 1)}}>+</button>
      { count }
    </div>
  )
}

或是你可以你可以透過 children,來避免相互引響而造成的重複渲染

const App = () => {
	return (
    <>
      <Counter>
        <SlowComponent />
      </Counter>
    </>
  )
}

const Counter = ({ children }) => {
	const [count, setCount] = useState(0)

	return (
    <div>
      <button onClick={() => {setCount(perv => perv + 1)}}>+</button>
      { count }
      { children }
    </div>
  )
}

兩派做法都有支持者

全部 component 都加上 memo vs 不使用 memo

先說 全部 component 都加上 memo 的觀點

以這篇文章 Why We Memo All the Things 的作者,他認為全部的 component 都需加上 memo,而且所有的 props 都使用 useMemo,他認為這樣可以增加開發者的開發時間,而且開發者也不用去思考我這邊是否要是否要使用 memo useMemo 或是 useCallback

不使用 memo 的觀點則是

認為大部分的 memo useMemouseCallback 都該移除,因為他們可能沒有帶給效能上的優化,反而增加了初次渲染的負擔,並增加了程式的複雜程度
因為大量使用 memo useMemouseCallback,首次渲染時,因為佔用了太多記憶體位址,所以會影響初次渲染的速度

但是不使用 memo 的話可能會將元件切分成更小的元件,會增加開發時間,命名難度,程式碼可讀性

所以其實兩派都各有優缺點,就看看你喜歡哪派了~

小結

其實一開始認識到 memo useCallback useMemo 會覺得好厲害,那我可以在專案上全部都使用嗎?
而我的觀點是,還是要是專案的實際情況為例,因為其實 re-render 重複渲染並不是壞事
而是在你該重複渲染的組件就讓他渲染吧,而不該渲染的元件就設計成讓他最低限度的炫染就好
這三個武器一定會有適合的使用時機~


上一篇
Day 20 memo vs useCallback vs useMemo
下一篇
Day 22 useReducer 有比 useState
系列文
我與 React 的 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言