iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
Modern Web

職缺資訊平台—Jobscanner系列 第 19

[開發] React 從 0 到 0.1 (3)

  • 分享至 

  • xImage
  •  

依據不同的條件判斷 render 對應的 JSX

// 根據 isPacked 決定是否顯示 ✔
if (isPacked) {
  return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;

<li className="item">...</li> 寫了兩次,如果要改 className 還要改兩個地方

為了降低重複性,可以使用三元運算子 (? :),改寫成:

return (
  <li className="item">
    {isPacked ? name + ' ✔' : name}
  </li>
);

在 React 元件中很常遇到 當某某條件符合時才 render 指定的 JSX,可以使用邏輯運算子 AND (&&) (在 JSX 填入 falsy 值,不會渲染出任何內容 (例如:null、undefined)),於是可以再改寫成:

return (
  <li className="item">
    {name} {isPacked && '✔'}
  </li>
);

*複習:寫出好讀好寫的 JS

&& (AND)

  1. 從左到右對運算元進行估值
  2. 將每一個運算元轉成 boolean,如果遇到結果為 false,馬上停止,立即回傳這個運算元的值
  3. 假設所有的運算元都已經被運算了(全部為 truthy),回傳最後一個運算元

渲染多個元件在畫面上,例如:以下清單,只有li的內容不一樣

<ul>
  <li>AAA</li>
  <li>BBBBBB</li>
  <li>CCCCCCCCC</li>
</ul>

可以將資料整理成陣列,使用Map 將每一個項目轉換成 JSX

const list = [
  'AAA',
  'BBBBBB',
  'CCCCCCCCC',
];

export default function List() {
  const listItems = list.map(item =>
    <li>{item}</li>
  );
  return <ul>{listItems}</ul>;
}

陣列中的每一個項目都必須要給 key,字串或是數字都可以,作為識別用!

  • key 是用來告訴 React,陣列中的每一個項目對應到的元件
  • 當陣列中有項目有異動時(更動順序、插入、刪除),key 讓 React 可以知道發生了什麽樣的異動,進一步做 DOM tree 的更新

key 怎麼來:

  • 若資料是從 Database 來的,通常每一筆資料會帶有 key/ID,可以作為 key
  • 資料若是從 local 端建置的,可以使用 counter、Crypto: randomUUID() 或是uuid Package。

key 規則:

  • 同一個陣列的項目,key 必須為唯一值
  • 不要更改 key

React 為什麽需要 key?

想像電腦桌面上每個檔案都沒有名字,為了要識別它們,可能會用數的方式,第一個檔案、第二個、第三個...
假設刪掉一個檔案,原本第二個的檔案會變成第一個,第三個變第二個...

資料夾中的檔案名稱就像 JSX key 用途一樣,在同一個集合中用來識別每一個項目

建議使用有意義或是能提供資訊內容作為 key,而不建議使用 index 位置作為 key
當陣列中有項目有異動時(更動順序、插入、刪除),使用 index 作為 key的方式很容易造成混淆

也不要使用 key={Math.random()}動態產生 key,這樣的寫法會在每次 React render 時都找不到 match 的key,變成每次都重建元件和 DOM。不只效能差,也會遺失原本使用在元件中輸入的內容。

在元件中是無法直接取用 key 的,如果元件需要使用 key 值,需另外做傳入,例如:userId <Profile key={id} userId={id} />


保持元件的 pure,只負責計算,數學公式就是個 pure function,例如:y=2x

如果 x = 3,y 不會一下變 -1、9 或是 100,永遠是 6

React 也是用一樣的概念,React 會假設每一個你寫的元件都是 pure function,代表每次傳入一樣的參數給這個元件,每次都必須得到一樣的結果,一樣的 JSX

React 的 render 過程也一定是 pure 的,元件只應該回傳它們的 JSX,不去更改在執行前就已經存在的其他物件或是變數

不正確範例:

let guest = 0;

function Cup() {
  // 更改原本就存在的變數 guest
  guest = guest + 1;
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup />
      <Cup />
      <Cup />
    </>
  );
}

元件針對一個在外部宣告的變數作讀取和寫入,代表每次呼叫這個元件都會得到不一樣的 JSX,如果有其他元件也要讀取 guest,會讓其他元件產生不符合預期的 JSX

可以將元件改成接收一個 guest prop,例如:

function Cup({ guest }) {
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup guest={1} />
      <Cup guest={2} />
      <Cup guest={3} />
    </>
  );
}

每一個元件都只要顧好自身的狀態就好


元件異動原先就已經存在的變數稱為 mutation,Pure function 是不會異動到 function scope 以外的變數或是物件!

但在更改同一個 function 內的變數是可以的,稱為 local mutation,例如:

function Cup({ guest }) {
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaGathering() {
  let cups = [];
  for (let i = 1; i <= 12; i++) {
    cups.push(<Cup key={i} guest={i} />);
  }
  return cups;
}

在 React 中 side effect 通常會在事件處理器(event handler)中發生,事件處理器在元件內部被定義,但它們不會在元件執行時被觸發,所以事件處理器不用是 Pure function!

*如果要更改 array,都記得要 clone 一份,再去改
*有些操作是會影響到 array 本身,例如:pushpopreversesort,但是像slicefiltermap 則是會建立一個新的陣列


上一篇
[開發] React 從 0 到 0.1 (2)
下一篇
[開發] React 從 0 到 0.1 (4)
系列文
職缺資訊平台—Jobscanner31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言