[30DaysChallenge] React 如何決定要不要渲染

30DaysChallenge 是自主性每兩天寫一篇技術相關的部落格

React

Reconciliation 是 React 的演算法

白話一點來說,就是在資料有變動之後,比較前後畫面的差別並決定要不要重新渲染

聽起來好像很簡單,但你知道就算一樣的畫面,他其實是不同的物件嗎?

<div>
  <Header />
</div>

<section>
  <Header />
</section>

上述例子,我們的 <header />,前者與後者是不同的獨立新元素

由於父元件(元素)的改變,就會使整個跟著改變

渲染的過程簡要會是

  • 當有資料不同時,先比較,進行新的 DOM tree 與舊的 DOM tree 有沒有差別
  • 比較過後發現有差別且畫面有進行變更,才會實際影像到真正的 DOM tree

KEY

先前有提到關於 KEY 的用法,我們加上 key 來讓 React 認識元件,可以提升渲染效能

官方的範例

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

什麼時候會進行比對? state 為甚麼不會不見?

React 會在幾個狀況下比對

  • 狀態變更 (state)
  • 傳入的屬性變更 (props)
  • 當某元件的函式執行了 (components function)

產生過後的新元件仍會保持原本的 state,這是因為 state 是存在 React 之中

並不會再被初始化,除非你手動重新整理、或是關掉網頁


React.memo / useMemo

React.memo

雖然 React 會評估 DOM 的差別,但有些地方永遠都一樣

可以使用 React.memo()來讓 react 知道說,如果這個元件沒有改變,忽略其後面的 child

也就是說,這個會讓 React 知道說若比對之後,仍為一樣的元件,就不會進行渲染

但這也會另外造成額外的運算

語法

export default memo(Header)

useMemo

當我們說重新渲染的時候,會讓整個元件裡面的每個東西,包含函式都重新渲染

所以我們的寫的監聽器或是其他函式,每次都會重新生成

因為 object !== object (詳情: JS Primitive type & Object type)

不管怎麼比較,看起來就是不一樣,就是會重新生成(執行)

React.memo 只能比對原始型別,那就用 useMemo 存放物件吧

用 useMemo 存放

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

告一段落 09/02