Reactでif文を使う方法|条件分岐の基本パターン3選
Reactでif文を使った条件分岐の方法を解説。JSXでの条件分岐、三項演算子、論理演算子を使った実践的なパターンを具体例とともに詳しく説明します。
みなさん、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>
);
}
&&
演算子を使うことで、条件分岐ができます。
isVisible
がtrue
の場合のみ、<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>
);
}
このコードでは、いくつかの条件分岐を使っています。
isLoggedIn
がtrue
の場合のみ、ウェルカムメッセージが表示されます。
hasNotifications
がtrue
の場合のみ、通知バッジが表示されます。
ログインしていない場合のメッセージも追加してみましょう。
{!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.isActive
がtrue
かチェックしています。
配列や文字列の条件分岐
配列の長さや文字列の有無でも条件分岐できます。
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つの異なるコンポーネントを条件によって切り替えています。
AdminPanel
とUserPanel
を別々に定義して、使い分けています。
コンポーネントを分離することで、コードが読みやすくなります。
三項演算子の読みやすい書き方
三項演算子が複雑になる場合は、改行を使って読みやすくしましょう。
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
を使うことで、フィルタリングの計算結果をメモ化しています。
items
やfilter
が変更された時だけ、再計算されます。
パフォーマンスの最適化も重要なポイントですね。
まとめ
お疲れさまでした!
Reactでの条件分岐について、詳しく見てきました。
3つの基本パターン
**論理演算子(&&)**は、単純な表示/非表示の制御に適しています。
コードが簡潔で読みやすく、ログイン状態やデータの有無による表示制御でよく使われます。
**三項演算子(? :)**は、二択の選択に適しています。
ボタンのテキスト切り替えやスタイルの変更などで活用できます。
関数内でのif文は、複雑な条件分岐や再利用可能なロジックに適しています。
多段階の条件分岐や複雑なロジックを含む場合は、このパターンが最も読みやすくなります。
使い分けのポイント
それぞれのパターンには適切な使用場面があります。
コードの可読性とメンテナンス性を考慮して選択することが重要です。
パフォーマンスを考慮する場合は、useMemo
などのReact Hooksと組み合わせて最適化しましょう。
今日から実践してみよう
ぜひ実際のプロジェクトで、これらのパターンを使い分けてみてください。
最初は迷うかもしれませんが、慣れてくれば自然に適切なパターンを選べるようになります。
より効率的で保守性の高いReactアプリケーションを開発していきましょう!
条件分岐をマスターすれば、Reactの表現力が格段に向上しますよ。