依據不同的條件判斷 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)
渲染多個元件在畫面上,例如:以下清單,只有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 怎麼來:
Crypto: randomUUID()
或是uuid
Package。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 本身,例如:push
、pop
、reverse
、sort
,但是像slice
、filter
、map
則是會建立一個新的陣列