第 9 章:條件渲染 (Conditional Rendering)

在實際的應用程式中,我們經常需要根據不同的條件來顯示不同的內容。例如,當使用者已登入時顯示歡迎訊息,當資料載入中時顯示載入指示器。React 提供了多種方式來實現條件渲染,讓我們可以根據狀態或 Props 動態地控制要渲染的內容。

9.1 條件渲染的基本概念

條件渲染是根據某些條件來決定要渲染哪些 JSX 元素的技術。在 React 中,你可以使用 JavaScript 的所有條件邏輯,包括 if 語句、三元運算子、邏輯運算子等。

9.2 使用 if/else 語句

最直接的條件渲染方式是使用 JavaScript 的 if 語句:

import React, { useState } from 'react';

function WelcomeMessage({ isLoggedIn, username }) {
  if (isLoggedIn) {
    return (
      <div>
        <h1>歡迎回來,{username}!</h1>
        <p>你上次的登入時間是昨天下午 3:00</p>
      </div>
    );
  } else {
    return (
      <div>
        <h1>歡迎訪問我們的網站</h1>
        <p>請登入以獲得完整體驗</p>
      </div>
    );
  }
}

function LoginExample() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [username, setUsername] = useState('用戶');

  return (
    <div>
      <button onClick={() => setIsLoggedIn(!isLoggedIn)}>
        {isLoggedIn ? '登出' : '登入'}
      </button>
      <WelcomeMessage isLoggedIn={isLoggedIn} username={username} />
    </div>
  );
}

export default LoginExample;

9.3 使用元素變數

你可以使用變數來儲存元素,然後根據條件來決定變數的值:

import React, { useState } from 'react';

function ShoppingCart() {
  const [items, setItems] = useState([
    { id: 1, name: '筆記本電腦', price: 25000, quantity: 1 },
    { id: 2, name: '滑鼠', price: 500, quantity: 2 }
  ]);

  const [isCheckingOut, setIsCheckingOut] = useState(false);

  const removeItem = (id) => {
    setItems(items.filter(item => item.id !== id));
  };

  const getTotalPrice = () => {
    return items.reduce((total, item) => total + (item.price * item.quantity), 0);
  };

  // 使用元素變數
  let cartContent;
  if (items.length === 0) {
    cartContent = (
      <div style={{ textAlign: 'center', padding: '20px' }}>
        <h3>購物車是空的</h3>
        <p>開始購物吧!</p>
      </div>
    );
  } else {
    cartContent = (
      <div>
        <h3>購物車 ({items.length} 項商品)</h3>
        {items.map(item => (
          <div key={item.id} style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            padding: '10px',
            borderBottom: '1px solid #eee'
          }}>
            <div>
              <strong>{item.name}</strong>
              <p>單價: ${item.price} × {item.quantity}</p>
            </div>
            <div>
              <span>${item.price * item.quantity}</span>
              <button 
                onClick={() => removeItem(item.id)}
                style={{ marginLeft: '10px', color: 'red' }}
              >
                移除
              </button>
            </div>
          </div>
        ))}
        <div style={{ textAlign: 'right', marginTop: '20px' }}>
          <strong>總計: ${getTotalPrice()}</strong>
        </div>
      </div>
    );
  }

  return (
    <div style={{ maxWidth: '500px', margin: '0 auto' }}>
      <h2>購物車範例</h2>
      {cartContent}

      {items.length > 0 && (
        <button 
          onClick={() => setIsCheckingOut(true)}
          style={{
            width: '100%',
            padding: '15px',
            backgroundColor: '#4CAF50',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            marginTop: '20px',
            cursor: 'pointer'
          }}
          disabled={isCheckingOut}
        >
          {isCheckingOut ? '處理中...' : '結帳'}
        </button>
      )}
    </div>
  );
}

export default ShoppingCart;

9.4 邏輯 AND 運算子 (&&)

邏輯 AND 運算子 (&&) 是 React 中最常用的條件渲染方式之一。當左側的條件為 true 時,右側的元素會被渲染;當左側為 false 時,什麼都不會渲染。

9.5 三元運算子 (Ternary Operator)

三元運算子 (condition ? trueCase : falseCase) 適用於需要在兩個選項之間選擇的情況。

9.6 複雜條件渲染

對於更複雜的條件邏輯,你可以創建函式來處理渲染邏輯。

9.7 條件渲染的最佳實踐

9.7.1 避免在 JSX 中使用過於複雜的條件邏輯

// ❌ 不好的做法:JSX 中的邏輯過於複雜
function BadExample({ user, isLoading, error }) {
  return (
    <div>
      {isLoading ? (
        <div>載入中...</div>
      ) : error ? (
        <div>錯誤: {error.message}</div>
      ) : user ? (
        user.isActive ? (
          user.subscription.isPremium ? (
            <div>高級會員:{user.name}</div>
          ) : (
            <div>普通會員:{user.name}</div>
          )
        ) : (
          <div>未啟用的使用者:{user.name}</div>
        )
      ) : (
        <div>請先登入</div>
      )}
    </div>
  );
}

// ✅ 好的做法:將邏輯提取到函式中
function GoodExample({ user, isLoading, error }) {
  const renderUserStatus = () => {
    if (isLoading) return <div>載入中...</div>;
    if (error) return <div>錯誤: {error.message}</div>;
    if (!user) return <div>請先登入</div>;

    if (!user.isActive) {
      return <div>未啟用的使用者:{user.name}</div>;
    }

    return (
      <div>
        {user.subscription.isPremium ? '高級' : '普通'}會員:{user.name}
      </div>
    );
  };

  return <div>{renderUserStatus()}</div>;
}

9.7.2 使用短路求值時要注意 falsy 值

function Examples() {
  const [count, setCount] = useState(0);
  const [items, setItems] = useState([]);

  return (
    <div>
      {/* ❌ 問題:當 count 為 0 時會顯示 0 */}
      {count && <div>計數: {count}</div>}

      {/* ✅ 正確:明確檢查條件 */}
      {count > 0 && <div>計數: {count}</div>}

      {/* ❌ 問題:當陣列為空時,length 為 0,會顯示 0 */}
      {items.length && <div>項目數: {items.length}</div>}

      {/* ✅ 正確:明確檢查陣列長度 */}
      {items.length > 0 && <div>項目數: {items.length}</div>}
    </div>
  );
}

9.8 總結

條件渲染是 React 中的一個基本而重要的概念,它讓我們能夠根據應用程式的狀態動態地顯示不同的內容。

本章重點:

  • 多種條件渲染方法:if/else、三元運算子、邏輯 AND 運算子
  • 元素變數:將條件邏輯從 JSX 中分離
  • 複雜條件處理:使用函式來處理複雜的渲染邏輯
  • 最佳實踐:避免 JSX 中的複雜邏輯,注意 falsy 值的處理

選擇條件渲染方法的建議:

  1. 簡單的顯示/隱藏:使用 && 運算子
  2. 二選一的情況:使用三元運算子
  3. 複雜的多分支邏輯:使用 if/else 語句或元素變數
  4. 非常複雜的邏輯:提取到單獨的函式中

掌握條件渲染讓你能夠建立更動態、更互動的使用者介面。在下一章中,我們將學習列表渲染,這是另一個構建動態 UI 的重要技術。

results matching ""

    No results matching ""