Skip to content

Instantly share code, notes, and snippets.

@jackyu
Last active December 2, 2021 02:59
Show Gist options
  • Save jackyu/8ea681ad72f337bc7fcc0fbff4f6938a to your computer and use it in GitHub Desktop.
Save jackyu/8ea681ad72f337bc7fcc0fbff4f6938a to your computer and use it in GitHub Desktop.
[筆記][React] 為什麼要在 React 中使用 key

為什麼要在 React 中使用 key 屬性

為什麼要在 React 中使用 key 屬性,一切的原因都是 "效能"。 主要的問題是, 每次應用程式渲染 Reacrt 時,都會建立一個新的 react 元素樹,這裡的問題是更新 UI 為了匹配在渲染中建立出來的新 react 元素樹。React 提供了一個聰明的做法讓解決這件事的時間複雜度從 O(n^3) 降低至 O(n),提供了以下二種假設

  1. 如果一個元素改變它的類型,就會建立一個新的樹
  2. 如果二個元素在兩顆樹中都有相同的 key id,則它們是相同的元素,不會從 0 重新渲染

Reconciliation algorithm

該演算法取決於根元素,有一些不同的做法。如果根元素變更另一種類型(或變更另一個標籤),將會重頭建立新的樹,如下:

<div>
  <Counter />
</div>

<span>
  <Counter />
</span>

Counter 不會被重新使用,而是會被重新建立掛載

另一個 React 處理很好的情況,是當我們有相同類型的 DOM 元素時,React 只會更新屬性並重用其結構,如下:

<!-- before -->
<img src="images/image.svg" className="something" />

<!-- after -->
<img src="images/image.svg" className="another-something" />

標籤保持不變,React 只會更新 className 屬性

<!-- before -->
<div style={{color: "green", padding: "10px"}}></div>

<!-- after -->
<div style={{color: "orange", padding: "10px"}}></div>

React 只會更新 color 樣式,padding 保持不變

如果節點變更,或不使用節點類型本身,只變更傳遞給它的屬性時,React 都會有所不同。但是有一個問題案例是無法通過查看節點或屬性解決,也就是 Lists Lists 具有相同的節點類型和屬性,因此它們不會被演算法認可,看下例

<!-- tree1 -->
<ul>
  <li>1</li>
  <li>2</li>
</ul>

<!-- tree2 -->
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

我們有二個 Lists,React 會匹配前兩二元素(1, 2),並在最後插入一個 (3),但如果我們有一個相似但不同的實作,如下:

<!-- tree1 -->
<ul>
  <li>2</li>
  <li>3</li>
</ul>

<!-- tree2 -->
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

我們在列表的開頭插入了一些新元素。 React 不知道如何處理這個問題,反而會重新建立每個元素,而不是重用在樹之間保變不變的 2 和 3,從而導致效能不佳

這就是 key 很重要的地方。使用 key,我們可以讓列表每一個項目都有一個唯一的識別代碼(ID), 因此 React 可以輕鬆檢測誰需要變更,或不變更,只重新渲染有變更的那些部分

參考來源

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment