你的元件通常需要根據不同的條件顯示不同的內容。在 React 中,你可以使用 JavaScript 語法(例如 if
陳述式、&&
和 ? :
運算子)來條件式渲染 JSX。
你將會學到
- 如何根據條件返回不同的 JSX
- 如何有條件地包含或排除一段 JSX
- 在 React 程式碼庫中常見的條件語法捷徑
條件式返回 JSX
假設你有一個 PackingList
元件渲染多個 Item
,這些項目可以標記為已打包或未打包
function Item({ name, isPacked }) { return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
請注意,某些 Item
元件的 isPacked
prop 設定為 true
而不是 false
。如果 isPacked={true}
,你想要在已打包的項目上新增一個核取記號 (✅)。
你可以將它寫成 if
/else
陳述式,如下所示
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
如果 isPacked
prop 為 true
,則此程式碼會**返回不同的 JSX 樹狀結構。** 經過此更改後,某些項目末尾會出現核取記號
function Item({ name, isPacked }) { if (isPacked) { return <li className="item">{name} ✅</li>; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
試著編輯在任一情況下返回的內容,看看結果如何變化!
請注意,你如何使用 JavaScript 的 if
和 return
陳述式來建立分支邏輯。在 React 中,控制流程(例如條件)是由 JavaScript 處理的。
使用 null
有條件地不返回任何內容
在某些情況下,你根本不想渲染任何內容。例如,假設你根本不想顯示已打包的項目。元件必須返回某些內容。在這種情況下,你可以返回 null
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
如果 isPacked
為 true,則元件將不返回任何內容,null
。否則,它將返回要渲染的 JSX。
function Item({ name, isPacked }) { if (isPacked) { return null; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
實際上,從元件返回 null
並不常見,因為這可能會讓嘗試渲染它的開發人員感到驚訝。更常見的情況是,你會在父元件的 JSX 中有條件地包含或排除該元件。以下是執行此操作的方法!
條件式包含 JSX
在前面的範例中,你控制了元件將返回哪個(如果有的話!)JSX 樹狀結構。你可能已經注意到渲染輸出中的一些重複
<li className="item">{name} ✅</li>
非常類似於
<li className="item">{name}</li>
兩個條件分支都會返回 <li className="item">...</li>
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
雖然這種重複無害,但它可能會使你的程式碼更難維護。如果你想更改 className
呢?你必須在程式碼中的兩個地方進行更改!在這種情況下,你可以有條件地包含一些 JSX 來使你的程式碼更 DRY(不要重複自己)。
條件(三元)運算符 (? :
)
JavaScript 有一個用於編寫條件表達式的簡潔語法 — 稱為 條件運算符 或「三元運算符」。
取代以下寫法
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
你可以這樣寫
return (
<li className="item">
{isPacked ? name + ' ✅' : name}
</li>
);
你可以將其理解為 *「如果 isPacked
為 true,則(?
)渲染 name + ' ✅'
,否則(:
)渲染 name
」*。
深入探討
如果你有物件導向程式設計的背景,你可能會認為上述兩個例子略有不同,因為其中一個例子可能會建立兩個不同的 <li>
「實例」。但 JSX 元素不是「實例」,因為它們不持有任何內部狀態,也不是真正的 DOM 節點。它們是輕量級的描述,就像藍圖一樣。所以這兩個例子實際上是*完全相等的*。保存和重置狀態 詳細說明了這是如何運作的。
現在假設你想將已完成項目的文字包裝到另一個 HTML 標籤中,例如 <del>
來將其刪除線。你可以新增更多換行符和括號,以便更容易在每種情況下巢狀更多 JSX
function Item({ name, isPacked }) { return ( <li className="item"> {isPacked ? ( <del> {name + ' ✅'} </del> ) : ( name )} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
這種樣式適用於簡單的條件,但請適量使用。如果你的元件因為過多巢狀的條件標記而變得混亂,請考慮提取子元件來清理程式碼。在 React 中,標記是你程式碼的一部分,因此你可以使用變數和函數等工具來整理複雜的表達式。
邏輯 AND 運算符 (&&
)
你會遇到的另一個常見捷徑是 JavaScript 邏輯 AND (&&
) 運算符。 在 React 元件中,當你想在條件為 true 時渲染一些 JSX,**否則不渲染任何東西時**,它經常出現。使用 &&
,你可以有條件地僅在 isPacked
為 true
時才渲染核取記號
return (
<li className="item">
{name} {isPacked && '✅'}
</li>
);
你可以將其理解為 *「如果 isPacked
,則(&&
) 渲染核取記號,否則,不渲染任何東西」*。
實際應用如下
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
JavaScript && 表達式 如果左側(我們的條件)為 true
,則返回其右側的值(在我們的例子中為核取記號)。但如果條件為 false
,則整個表達式變為 false
。React 將 false
視為 JSX 樹中的「空洞」,就像 null
或 undefined
一樣,並且不會在其位置渲染任何東西。
有條件地將 JSX 分配給變數
當捷徑妨礙編寫簡潔的程式碼時,請嘗試使用 if
陳述式和變數。你可以重新分配使用 let
定義的變數,因此首先提供你要顯示的預設內容,即名稱
let itemContent = name;
如果 isPacked
為 true
,請使用 if
陳述式將 JSX 表達式重新分配給 itemContent
if (isPacked) {
itemContent = name + " ✅";
}
大括號開啟了「通往 JavaScript 的視窗」。 在返回的 JSX 樹中使用大括號嵌入變數,將先前計算的表達式嵌套在 JSX 內部
<li className="item">
{itemContent}
</li>
這種風格最冗長,但也最靈活。以下是實際應用
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = name + " ✅"; } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
和之前一樣,這不僅適用於文字,也適用於任意 JSX
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = ( <del> {name + " ✅"} </del> ); } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
如果您不熟悉 JavaScript,一開始可能會覺得這些樣式令人不知所措。但是,學習它們將幫助您讀寫任何 JavaScript 程式碼,而不僅僅是 React 元件!首先選擇您喜歡的樣式,如果您忘記其他樣式如何運作,請再次參考此處。
重點回顧
- 在 React 中,您可以使用 JavaScript 控制分支邏輯。
- 您可以使用
if
陳述式有條件地返回 JSX 表達式。 - 您可以有條件地將一些 JSX 儲存到變數中,然後使用大括號將其包含在其他 JSX 中。
- 在 JSX 中,
{cond ? <A /> : <B />}
表示 *「如果cond
,則渲染<A />
,否則渲染<B />
」*。 - 在 JSX 中,
{cond && <A />}
表示 *「如果cond
,則渲染<A />
,否則不渲染任何內容」*。 - 這些捷徑很常見,但如果您喜歡普通的
if
,則不必使用它們。
挑戰 1之 3: 使用 ? :
顯示未完成項目的圖示
如果 isPacked
不是 true
,請使用條件運算子(cond ? a : b
)來渲染 ❌。
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }