Reactでif文を使う方法|条件分岐の基本パターン3選

Reactでif文を使った条件分岐の方法を解説。JSXでの条件分岐、三項演算子、論理演算子を使った実践的なパターンを具体例とともに詳しく説明します。

Learning Next 運営
31 分で読めます

みなさん、Reactで条件分岐を書く時に困ったことはありませんか?

「JSXの中でif文を使いたいけど、どう書けばいいの?」 「条件によって違うコンポーネントを表示したい」 「もっと簡潔に条件分岐を書く方法はないの?」

こんな疑問を持っている方も多いでしょう。

実は、Reactでの条件分岐は通常のJavaScriptとは少し違います。 でも大丈夫です!

この記事では、Reactでif文を使った条件分岐の基本的な方法を詳しく解説します。

JSXでの条件分岐から実践的なパターンまで、具体例を使って分かりやすく説明しますね。

最後まで読めば、きっと条件分岐をスムーズに書けるようになりますよ!

Reactでの条件分岐の基本概念

まず、Reactでの条件分岐の基本を理解しましょう。

通常のJavaScriptとは、ちょっと違うポイントがあります。

JSXでの条件分岐の制限

最初に、やってはいけない書き方を見てみましょう。

// NG: JSXの中で直接if文は使えない
function BadExample() {
  return (
    <div>
      {if (true) {
        return <p>表示されます</p>;
      }}
    </div>
  );
}

このコードは、エラーになってしまいます。

なぜなら、JSXは式(expression)のみを受け入れるからです。

if文は**文(statement)**なので、直接使えないんです。

では、正しい書き方はどうでしょうか?

// OK: 条件分岐の基本的な書き方
function GoodExample() {
  const isVisible = true;
  
  return (
    <div>
      {isVisible && <p>表示されます</p>}
    </div>
  );
}

&&演算子を使うことで、条件分岐ができます。

isVisibletrueの場合のみ、<p>タグが表示されます。

条件分岐の基本パターン

Reactでは、主に3つのパターンで条件分岐を実装します。

1. 論理演算子(&&)

{condition && <Component />}

2. 三項演算子(? :)

{condition ? <ComponentA /> : <ComponentB />}

3. 関数内でのif文

function renderComponent() {
  if (condition) {
    return <ComponentA />;
  }
  return <ComponentB />;
}

それぞれに適した使用場面があります。

詳しく見ていきましょう!

パターン1: 論理演算子(&&)を使った条件分岐

論理演算子を使った条件分岐は、最もシンプルで読みやすい方法です。

「条件が真の場合のみ表示する」時に使います。

基本的な使い方

まず、シンプルな例から見てみましょう。

import React, { useState } from 'react';

function LogicalAndExample() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [hasNotifications, setHasNotifications] = useState(true);

  return (
    <div>
      <h1>ダッシュボード</h1>
      
      {/* ログイン状態によってメッセージを表示 */}
      {isLoggedIn && (
        <p>ようこそ、ダッシュボードにお越しいただきありがとうございます。</p>
      )}
      
      {/* 通知がある場合のみバッジを表示 */}
      {hasNotifications && (
        <div className="notification-badge">
          新しい通知があります
        </div>
      )}
    </div>
  );
}

このコードでは、いくつかの条件分岐を使っています。

isLoggedIntrueの場合のみ、ウェルカムメッセージが表示されます。

hasNotificationstrueの場合のみ、通知バッジが表示されます。

ログインしていない場合のメッセージも追加してみましょう。

{!isLoggedIn && (
  <p>ログインしてください。</p>
)}

!を使うことで、条件を反転させることができます。

複数の条件を組み合わせる

条件を組み合わせることもできます。

function MultipleConditions() {
  const [user, setUser] = useState({ 
    name: '田中太郎', 
    role: 'admin', 
    isActive: true 
  });

  return (
    <div>
      <h1>ユーザー管理</h1>
      
      {/* ユーザーが存在し、アクティブな場合のみ表示 */}
      {user && user.isActive && (
        <div>
          <p>ユーザー名: {user.name}</p>
          <p>役割: {user.role}</p>
        </div>
      )}
      
      {/* 管理者でアクティブな場合のみ管理パネルを表示 */}
      {user && user.role === 'admin' && user.isActive && (
        <div className="admin-panel">
          <h2>管理者パネル</h2>
          <button>ユーザー一覧</button>
          <button>設定</button>
        </div>
      )}
    </div>
  );
}

複数の条件を&&で繋げることで、より複雑な条件分岐ができます。

user && user.isActiveでは、まずuserが存在するかチェックしています。

その後、user.isActivetrueかチェックしています。

配列や文字列の条件分岐

配列の長さや文字列の有無でも条件分岐できます。

function ArrayAndStringConditions() {
  const [items, setItems] = useState(['りんご', 'みかん', 'バナナ']);
  const [message, setMessage] = useState('');

  return (
    <div>
      <h1>アイテム一覧</h1>
      
      {/* 配列にアイテムがある場合のみリストを表示 */}
      {items.length > 0 && (
        <ul>
          {items.map((item, index) => (
            <li key={index}>{item}</li>
          ))}
        </ul>
      )}
      
      {/* アイテムがない場合のメッセージ */}
      {items.length === 0 && (
        <p>アイテムがありません</p>
      )}
      
      {/* メッセージがある場合のみ表示 */}
      {message && (
        <div className="message">
          {message}
        </div>
      )}
    </div>
  );
}

items.length > 0で配列にアイテムがあるかチェックしています。

messageで文字列が空でないかチェックしています。

論理演算子使用時の注意点

論理演算子を使う時は、いくつか注意点があります。

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

  return (
    <div>
      <h1>注意点の例</h1>
      
      {/* NG: 0がfalseとして扱われ、0が表示されてしまう */}
      {count && <p>アイテム数: {count}</p>}
      
      {/* OK: 明示的に比較を行う */}
      {count > 0 && <p>アイテム数: {count}</p>}
      
      {/* OK: Boolean()を使って明示的に真偽値に変換 */}
      {Boolean(count) && <p>アイテム数: {count}</p>}
    </div>
  );
}

0はfalseとして扱われるので、そのまま表示されてしまいます。

明示的にcount > 0と比較することで、正しく動作します。

これって、結構引っかかりやすいポイントですね。

パターン2: 三項演算子(? :)を使った条件分岐

三項演算子は、条件に応じて2つの選択肢から1つを選ぶ際に使用します。

「AまたはB」の二択の時に便利です。

基本的な使い方

基本的な構文は条件 ? 真の場合 : 偽の場合です。

import React, { useState } from 'react';

function TernaryOperatorExample() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [theme, setTheme] = useState('light');

  return (
    <div className={theme === 'dark' ? 'dark-theme' : 'light-theme'}>
      <h1>ホーム</h1>
      
      {/* ログイン状態によってボタンの表示を変更 */}
      <button onClick={() => setIsLoggedIn(!isLoggedIn)}>
        {isLoggedIn ? 'ログアウト' : 'ログイン'}
      </button>
      
      {/* ログイン状態によってメッセージを変更 */}
      <p>
        {isLoggedIn 
          ? 'ようこそ、ダッシュボードへ' 
          : 'ログインしてください'
        }
      </p>
    </div>
  );
}

このコードでは、複数の場所で三項演算子を使っています。

classNameでは、テーマに応じてCSSクラスを切り替えています。

ボタンのテキストでは、ログイン状態に応じて「ログアウト」「ログイン」を切り替えています。

コンポーネントの条件分岐

異なるコンポーネントを条件によって表示することもできます。

function ComponentConditionalRendering() {
  const [userRole, setUserRole] = useState('guest');
  const [isLoading, setIsLoading] = useState(false);

  // 管理者用コンポーネント
  const AdminPanel = () => (
    <div className="admin-panel">
      <h2>管理者パネル</h2>
      <button>ユーザー管理</button>
      <button>システム設定</button>
    </div>
  );

  // 一般ユーザー用コンポーネント
  const UserPanel = () => (
    <div className="user-panel">
      <h2>ユーザーパネル</h2>
      <button>プロフィール編集</button>
      <button>設定</button>
    </div>
  );

  return (
    <div>
      <h1>ダッシュボード</h1>
      
      {/* ローディング状態の処理 */}
      {isLoading ? (
        <div className="loading">
          <p>読み込み中...</p>
        </div>
      ) : (
        <div>
          {/* ユーザーの役割に応じてコンポーネントを切り替え */}
          {userRole === 'admin' ? <AdminPanel /> : <UserPanel />}
        </div>
      )}
    </div>
  );
}

ここでは、2つの異なるコンポーネントを条件によって切り替えています。

AdminPanelUserPanelを別々に定義して、使い分けています。

コンポーネントを分離することで、コードが読みやすくなります

三項演算子の読みやすい書き方

三項演算子が複雑になる場合は、改行を使って読みやすくしましょう

function ReadableTernaryExample() {
  const [user, setUser] = useState({
    name: '田中太郎',
    role: 'admin',
    isActive: true,
    notifications: 5
  });

  return (
    <div>
      <h1>ユーザー情報</h1>
      
      {/* 改行を使って読みやすくする */}
      <div className="user-info">
        <p>
          ユーザー名: {
            user.name 
              ? user.name 
              : '未設定'
          }
        </p>
        
        <p>
          役割: {
            user.role === 'admin' 
              ? '管理者' 
              : user.role === 'user' 
              ? '一般ユーザー' 
              : 'ゲスト'
          }
        </p>
        
        <p>
          通知: {
            user.notifications > 0 
              ? `${user.notifications}件の新着通知` 
              : '新着通知はありません'
          }
        </p>
      </div>
    </div>
  );
}

改行を使って、条件と結果を見やすく配置しています。

複雑な条件分岐でも、これなら読みやすいですね。

でも、あまり複雑になりすぎる場合は、関数に分離した方が良いでしょう。

関数を使って条件分岐を整理

複雑な条件分岐は、関数として分離することもできます。

// 条件分岐を関数として分離
function renderUserActions(user) {
  if (user.role === 'admin') {
    return (
      <div>
        <button>ユーザー管理</button>
        <button>システム設定</button>
        <button>ログ確認</button>
      </div>
    );
  }
  
  if (user.role === 'user') {
    return (
      <div>
        <button>プロフィール編集</button>
        <button>設定</button>
      </div>
    );
  }
  
  return (
    <div>
      <button>ログイン</button>
      <button>新規登録</button>
    </div>
  );
}

関数に分離することで、メインコンポーネントがシンプルになります

条件分岐のロジックも理解しやすくなりますね。

パターン3: 関数内でのif文を使った条件分岐

複雑な条件分岐は、関数内でif文を使用する方が読みやすくなります。

JSXの中に長い条件分岐を書くより、スッキリします。

基本的な関数分離

まず、基本的な関数分離の例を見てみましょう。

import React, { useState } from 'react';

function FunctionBasedConditionalRendering() {
  const [user, setUser] = useState({
    name: '田中太郎',
    role: 'admin',
    isActive: true,
    lastLogin: new Date('2023-12-01'),
    notifications: 3
  });

  const [currentPage, setCurrentPage] = useState('dashboard');

  // ユーザー状態に応じたメッセージを返す関数
  const getUserStatusMessage = () => {
    if (!user.isActive) {
      return '⚠️ アカウントが無効化されています';
    }
    
    const daysSinceLogin = Math.floor((Date.now() - user.lastLogin) / (1000 * 60 * 60 * 24));
    
    if (daysSinceLogin > 30) {
      return '⚠️ 長期間ログインしていません';
    }
    
    if (daysSinceLogin > 7) {
      return '💡 しばらくログインしていません';
    }
    
    return '✅ アクティブなユーザーです';
  };

  return (
    <div>
      <header>
        <h1>マイアプリ</h1>
      </header>
      
      <footer>
        <p>{getUserStatusMessage()}</p>
      </footer>
    </div>
  );
}

この例では、getUserStatusMessage関数で複雑な条件分岐を処理しています。

アカウントの状態によって、異なるメッセージを返します。

最終ログイン日から日数を計算して、適切なメッセージを表示します。

関数に分離することで、ロジックが明確になりますね。

通知バッジを表示する関数

通知の数に応じて、異なるスタイルのバッジを表示してみましょう。

// 通知バッジを表示する関数
const renderNotificationBadge = () => {
  if (user.notifications === 0) {
    return null;
  }
  
  if (user.notifications > 99) {
    return <span className="badge red">99+</span>;
  }
  
  if (user.notifications > 10) {
    return <span className="badge orange">{user.notifications}</span>;
  }
  
  return <span className="badge blue">{user.notifications}</span>;
};

この関数では、通知数に応じて以下のように処理しています:

  • 0件の場合:何も表示しない(nullを返す)
  • 100件以上の場合:赤いバッジで「99+」を表示
  • 11件以上の場合:オレンジのバッジで数字を表示
  • それ以外の場合:青いバッジで数字を表示

段階的に条件をチェックすることで、適切なバッジを表示できます。

ページコンテンツを返す関数

ナビゲーションに応じて、異なるページコンテンツを表示してみましょう。

// ページコンテンツを返す関数
const renderPageContent = () => {
  if (currentPage === 'dashboard') {
    return (
      <div>
        <h2>ダッシュボード</h2>
        <p>最新の情報をご確認ください。</p>
      </div>
    );
  }
  
  if (currentPage === 'profile') {
    return (
      <div>
        <h2>プロフィール</h2>
        <p>名前: {user.name}</p>
        <p>役割: {user.role}</p>
        <p>状態: {getUserStatusMessage()}</p>
      </div>
    );
  }
  
  if (currentPage === 'settings') {
    return (
      <div>
        <h2>設定</h2>
        <p>アカウント設定を変更できます。</p>
      </div>
    );
  }
  
  // デフォルトケース
  return (
    <div>
      <h2>ページが見つかりません</h2>
      <p>指定されたページは存在しません。</p>
    </div>
  );
};

この関数では、現在のページに応じて異なるコンテンツを返しています。

デフォルトケースも用意しているので、予期しない値でもエラーになりません。

複雑な条件分岐の整理

より複雑な例として、注文管理システムを見てみましょう。

function ComplexConditionalLogic() {
  const [order, setOrder] = useState({
    id: 'ORD-001',
    status: 'processing',
    total: 15000,
    customer: {
      name: '田中太郎',
      isPremium: true,
      address: '東京都渋谷区'
    },
    paymentMethod: 'credit_card',
    shippingMethod: 'express'
  });

  // 注文状態のスタイルを決定する関数
  const getOrderStatusStyle = () => {
    const baseStyle = {
      padding: '8px 16px',
      borderRadius: '4px',
      fontWeight: 'bold',
      display: 'inline-block'
    };

    if (order.status === 'pending') {
      return { ...baseStyle, backgroundColor: '#ffeaa7', color: '#2d3436' };
    }
    
    if (order.status === 'processing') {
      return { ...baseStyle, backgroundColor: '#74b9ff', color: '#ffffff' };
    }
    
    if (order.status === 'shipped') {
      return { ...baseStyle, backgroundColor: '#00b894', color: '#ffffff' };
    }
    
    if (order.status === 'delivered') {
      return { ...baseStyle, backgroundColor: '#00b894', color: '#ffffff' };
    }
    
    return { ...baseStyle, backgroundColor: '#ddd', color: '#000' };
  };

  return (
    <div>
      <h1>注文管理</h1>
      
      <div className="order-header">
        <h2>注文番号: {order.id}</h2>
        <div style={getOrderStatusStyle()}>
          {order.status}
        </div>
      </div>
    </div>
  );
}

この例では、getOrderStatusStyle関数で注文ステータスに応じたスタイルを決定しています。

ベースとなるスタイルを定義して、ステータスに応じて色を変更しています。

オブジェクトを使ったスタイルも、条件分岐で簡単に切り替えられます。

利用可能なアクションを決定する関数

注文状態に応じて、利用可能なアクションを決定してみましょう。

// 利用可能なアクションを決定する関数
const getAvailableActions = () => {
  const actions = [];
  
  if (order.status === 'pending') {
    actions.push({ label: '注文確認', action: () => alert('注文を確認しました') });
    actions.push({ label: 'キャンセル', action: () => alert('注文をキャンセルしました') });
  }
  
  if (order.status === 'processing') {
    actions.push({ label: '発送', action: () => alert('発送しました') });
    actions.push({ label: 'キャンセル', action: () => alert('注文をキャンセルしました') });
  }
  
  if (order.status === 'shipped') {
    actions.push({ label: '配送状況確認', action: () => alert('配送状況を確認します') });
  }
  
  if (order.status === 'delivered') {
    actions.push({ label: '返品', action: () => alert('返品手続きを開始します') });
    actions.push({ label: '再注文', action: () => alert('再注文します') });
  }
  
  return actions;
};

この関数では、注文状態に応じて利用可能なアクションを配列で返しています。

各アクションにはlabel(表示テキスト)とaction(実行する関数)が含まれています。

柔軟でスケーラブルなデザインですね。

実践的な使い分けガイド

3つのパターンをどのように使い分けるかのガイドをまとめました。

実際の開発では、どのパターンを選ぶかが重要です。

使い分けの基準

それぞれのパターンに適した使用場面を見てみましょう。

function ConditionalRenderingGuide() {
  const [showExample, setShowExample] = useState(true);
  const [userRole, setUserRole] = useState('user');
  const [items, setItems] = useState([1, 2, 3]);

  return (
    <div>
      <h1>条件分岐の使い分け</h1>
      
      {/* 1. 単純な表示/非表示 → 論理演算子 */}
      <section>
        <h2>1. 論理演算子(&&)- 単純な表示/非表示</h2>
        {showExample && (
          <div>
            <p>✅ 使用場面:</p>
            <ul>
              <li>コンポーネントやメッセージの表示/非表示</li>
              <li>ログイン状態による表示制御</li>
              <li>データの有無による表示制御</li>
            </ul>
          </div>
        )}
      </section>
      
      {/* 2. 二択の選択 → 三項演算子 */}
      <section>
        <h2>2. 三項演算子(? :)- 二択の選択</h2>
        <div>
          <p>✅ 使用場面:</p>
          <ul>
            <li>ボタンのテキスト切り替え</li>
            <li>スタイルの切り替え</li>
            <li>簡単な値の選択</li>
          </ul>
          
          <button>
            {showExample ? '非表示にする' : '表示する'}
          </button>
        </div>
      </section>
      
      {/* 3. 複雑な条件分岐 → 関数内if文 */}
      <section>
        <h2>3. 関数内if文 - 複雑な条件分岐</h2>
        <div>
          <p>✅ 使用場面:</p>
          <ul>
            <li>多段階の条件分岐</li>
            <li>複雑なロジックを含む表示制御</li>
            <li>再利用可能な条件分岐</li>
          </ul>
        </div>
      </section>
    </div>
  );
}

使い分けのまとめ

以下の表で、使い分けのポイントをまとめました:

パターン別の特徴

  • 論理演算子(&&):単純な表示/非表示、可読性が高い
  • 三項演算子(? :):二択の選択、中程度の可読性
  • 関数内if文:複雑な条件分岐、高い可読性とメンテナンス性

選択の基準

  • 単純な表示/非表示 → 論理演算子
  • 二択の選択 → 三項演算子
  • 複雑な条件分岐 → 関数内if文

パフォーマンスを考慮した条件分岐

大量のデータを扱う場合は、パフォーマンスも考慮しましょう。

import React, { useState, useMemo } from 'react';

function PerformanceOptimizedConditionalRendering() {
  const [filter, setFilter] = useState('all');
  const [items, setItems] = useState([
    { id: 1, name: 'アイテム1', category: 'A', active: true },
    { id: 2, name: 'アイテム2', category: 'B', active: false },
    { id: 3, name: 'アイテム3', category: 'A', active: true },
  ]);

  // 重い計算をuseMemoでメモ化
  const filteredItems = useMemo(() => {
    if (filter === 'all') {
      return items;
    }
    
    if (filter === 'active') {
      return items.filter(item => item.active);
    }
    
    if (filter === 'inactive') {
      return items.filter(item => !item.active);
    }
    
    return items.filter(item => item.category === filter);
  }, [items, filter]);

  return (
    <div>
      <h1>パフォーマンス最適化された条件分岐</h1>
      
      <div className="results-info">
        <p>表示中: {filteredItems.length}件</p>
      </div>
      
      <div className="items-grid">
        {filteredItems.map(item => (
          <div key={item.id} className="item-card">
            <h4>{item.name}</h4>
            <p>カテゴリ: {item.category}</p>
            <p>状態: {item.active ? 'アクティブ' : '非アクティブ'}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

useMemoを使うことで、フィルタリングの計算結果をメモ化しています。

itemsfilterが変更された時だけ、再計算されます。

パフォーマンスの最適化も重要なポイントですね。

まとめ

お疲れさまでした!

Reactでの条件分岐について、詳しく見てきました。

3つの基本パターン

**論理演算子(&&)**は、単純な表示/非表示の制御に適しています。

コードが簡潔で読みやすく、ログイン状態やデータの有無による表示制御でよく使われます。

**三項演算子(? :)**は、二択の選択に適しています。

ボタンのテキスト切り替えやスタイルの変更などで活用できます。

関数内でのif文は、複雑な条件分岐や再利用可能なロジックに適しています。

多段階の条件分岐や複雑なロジックを含む場合は、このパターンが最も読みやすくなります。

使い分けのポイント

それぞれのパターンには適切な使用場面があります。

コードの可読性とメンテナンス性を考慮して選択することが重要です。

パフォーマンスを考慮する場合は、useMemoなどのReact Hooksと組み合わせて最適化しましょう。

今日から実践してみよう

ぜひ実際のプロジェクトで、これらのパターンを使い分けてみてください。

最初は迷うかもしれませんが、慣れてくれば自然に適切なパターンを選べるようになります。

より効率的で保守性の高いReactアプリケーションを開発していきましょう!

条件分岐をマスターすれば、Reactの表現力が格段に向上しますよ。

関連記事