π― What is the Ternary Operator?
Imagine you're choosing between two doors:
THE && OPERATOR (Previous):
Like a light switch - ON or OFF
βββββββββββββββββββββββββββββββββββββββββββ
β {isOpen && <OpenSign />} β
β β
β ON (true): π‘ Light shows β
β OFF (false): β« Nothing (darkness) β
β β
β Problem: What if you want a "CLOSED" β
β sign when the light is off? β
βββββββββββββββββββββββββββββββββββββββββββ
THE TERNARY OPERATOR (New):
Like a railroad switch - Track A OR Track B
βββββββββββββββββββββββββββββββββββββββββββ
β {isOpen ? <OpenSign /> : <ClosedSign />}β
β β
β TRUE: β Goes to <OpenSign /> β
β FALSE: β Goes to <ClosedSign /> β
β β
β Always shows SOMETHING, never nothing! β
β You choose what appears in both cases β
βββββββββββββββββββββββββββββββββββββββββββ
REAL WORLD EXAMPLE:
Restaurant Sign:
βββββββββββββββββββββββββββββββββββββββββββ
β {isOpen ? ( β
β <div className="open"> β
β π’ WE'RE OPEN! β
β <button>Order Now</button> β
β </div> β
β ) : ( β
β <div className="closed"> β
β π΄ CLOSED β
β Open tomorrow at 12:00 β
β </div> β
β )} β
βββββββββββββββββββββββββββββββββββββββββββ
β οΈ The Big Problem: "Why Can't I Use If-Else?"
// ==========================================
// THE "IF-ELSE IN JSX" TRAP
// ==========================================
// β WRONG: Trying to use if-else statement inside JSX
function BadIfElse() {
const isOpen = false;
return (
<div>
{
if (isOpen) { // β ERROR! "Unexpected token"
return <p>Open</p>; // Statements don't produce values!
} else {
return <p>Closed</p>;
}
}
</div>
);
}
// Why it fails:
// - if/else is a STATEMENT (does action, returns nothing)
// - JSX {} needs an EXPRESSION (produces value)
// - It's like trying to put a verb where a noun should be!
// β
CORRECT: Ternary operator (expression that produces value)
function GoodTernary() {
const isOpen = false;
return (
<div>
{
isOpen // Condition
? <p>Open</p> // If true, return this
: <p>Closed</p> // If false, return this
}
</div>
);
}
// Visual comparison:
// STATEMENT (if/else): EXPRESSION (ternary):
// if (x) { x ? a : b
// return a; β
// } else { Produces VALUE
// return b; Can use in JSX {}
// }
// β
// Does action, no value
// Cannot use in JSX
// ==========================================
// THE "FORGETTING THE ELSE" TRAP
// ==========================================
// β WRONG: Ternary without else (incomplete)
function BadIncomplete() {
const isAdmin = true;
return (
<div>
{isAdmin ? <p>Admin Panel</p>} // β Missing : else part!
</div>
);
}
// Result: Syntax error!
// β
CORRECT: Must have both ? and :
function GoodComplete() {
const isAdmin = true;
return (
<div>
{isAdmin ? (
<p>Admin Panel</p>
) : (
<p>User Dashboard</p>
)}
</div>
);
}
// If you want nothing in else, use null:
{isAdmin ? <p>Admin</p> : null} // β
Valid!
// Or better yet, use && operator:
{isAdmin && <p>Admin</p>} // β
Cleaner for "all or nothing"
π Complete Basic Examples
Create file: react-ternary-operator.js
// ==========================================
// TERNARY OPERATOR - Complete Guide
// ==========================================
/*
TERNARY OPERATOR STRUCTURE:
βββββββββββββββββββββββββββββββββββββββββββ
β condition ? valueIfTrue : valueIfFalse β
β β
β Three parts: β
β 1. condition (must be true/false) β
β 2. ? (question mark - "then") β
β 3. valueIfTrue (what to return) β
β 4. : (colon - "else") β
β 5. valueIfFalse (what to return) β
β β
β Like a compact if-else: β
β if (condition) { β
β return valueIfTrue; β
β } else { β
β return valueIfFalse; β
β } β
βββββββββββββββββββββββββββββββββββββββββββ
*/
// ==========================================
// EXAMPLE 1: Basic Restaurant Open/Closed (From Your Text)
// ==========================================
function Footer() {
const hour = new Date().getHours();
const isOpen = hour >= 12 && hour <= 22;
return (
<footer className="footer">
{/* Ternary with simple text */}
{isOpen ? (
<div className="order">
<p>We're open until 22:00. Come visit us!</p>
<button className="btn">Order</button>
</div>
) : (
<p>We're happy to welcome you between 12:00 and 22:00.</p>
)}
</footer>
);
}
// Visual Flow:
// Time: 3 PM (15:00)
// isOpen = true
// {true ? <Open /> : <Closed />}
// β
// Returns <Open />
// β
// Renders open message + button
// Time: 11 PM (23:00)
// isOpen = false
// {false ? <Open /> : <Closed />}
// β
// Returns <Closed />
// β
// Renders closed message
// ==========================================
// EXAMPLE 2: Menu with Empty State (From Your Text)
// ==========================================
function Menu() {
const pizzas = [
{ name: "Margherita", price: 10 },
{ name: "Pepperoni", price: 12 }
];
const numPizzas = pizzas.length;
return (
<main className="menu">
<h2>Our Menu</h2>
{/* Ternary: Show menu OR empty message */}
{numPizzas > 0 ? (
<>
<p>Authentic Italian cuisine. {numPizzas} dishes to choose from.</p>
<ul className="pizzas">
{pizzas.map(pizza => (
<li key={pizza.name}>{pizza.name} - ${pizza.price}</li>
))}
</ul>
</>
) : (
<p>We're still working on our menu. Please come back later :)</p>
)}
</main>
);
}
// Comparison: && vs Ternary
// βββββββββββββββββββ¬ββββββββββββββββββββββββββ
// β && Operator β Ternary Operator β
// βββββββββββββββββββΌββββββββββββββββββββββββββ€
// β {hasItems && β {hasItems ? β
// <ShowItems />} β <ShowItems /> : β
// β <ShowEmpty /> β
// β } β
// βββββββββββββββββββΌββββββββββββββββββββββββββ€
// β Shows nothing β Shows alternative β
// β if false β if false β
// βββββββββββββββββββΌββββββββββββββββββββββββββ€
// β "All or nothing"β "Either/Or" β
// βββββββββββββββββββΌββββββββββββββββββββββββββ€
// β Good for: β Good for: β
// β - Optional UI β - Toggle between views β
// β - Badges β - Login/Logout states β
// β - Notifications β - Loading/Error/Success β
// βββββββββββββββββββ΄ββββββββββββββββββββββββββ
// ==========================================
// EXAMPLE 3: User Authentication States
// ==========================================
function UserDashboard({ user, isLoading, error }) {
return (
<div className="dashboard">
{/* Loading state */}
{isLoading ? (
<div className="spinner">Loading user data...</div>
) : error ? (
<div className="error">Error: {error.message}</div>
) : user ? (
<div className="user-profile">
<h1>Welcome, {user.name}!</h1>
<p>Email: {user.email}</p>
{user.isAdmin ? (
<AdminPanel />
) : (
<UserPanel />
)}
</div>
) : (
<div className="login-prompt">
<p>Please log in to continue</p>
<button>Login</button>
</div>
)}
</div>
);
}
// Nested ternaries (use sparingly, can get confusing):
// isLoading ? Loading : error ? Error : user ? User : Login
// β β β β β β
// 1st check 1st yes 1st no 2nd yes 2nd no 3rd no
// ==========================================
// EXAMPLE 4: Styling with Ternary
// ==========================================
function StatusBadge({ status }) {
// Different styles based on status
const badgeStyle = {
padding: '8px 16px',
borderRadius: '20px',
fontWeight: 'bold',
color: 'white',
// Ternary in object property
backgroundColor: status === 'success' ? '#4caf50' :
status === 'warning' ? '#ff9800' :
status === 'error' ? '#f44336' : '#9e9e9e'
};
const message = status === 'success' ? 'β Completed' :
status === 'warning' ? 'β Warning' :
status === 'error' ? 'β Failed' :
'βΉ Unknown';
return (
<span style={badgeStyle}>
{message}
</span>
);
}
// Usage:
// <StatusBadge status="success" /> // Green
// <StatusBadge status="warning" /> // Orange
// <StatusBadge status="error" /> // Red
// ==========================================
// EXAMPLE 5: Form Input States
// ==========================================
function InputField({ value, onChange, isValid, isTouched }) {
return (
<div className="input-group">
<input
value={value}
onChange={onChange}
className={isValid ? 'valid' : isTouched ? 'invalid' : ''}
style={{
borderColor: isValid ? '#4caf50' :
isTouched ? '#f44336' : '#ccc',
backgroundColor: isValid ? '#e8f5e9' :
isTouched ? '#ffebee' : 'white'
}}
/>
{/* Show validation message */}
{isTouched && !isValid ? (
<p className="error-message">Please fix this field</p>
) : isValid ? (
<p className="success-message">β Looks good!</p>
) : null}
</div>
);
}
// ==========================================
// EXAMPLE 6: Ternary vs If-Else Outside JSX
// ==========================================
// Sometimes it's cleaner to use if-else BEFORE the return
function MenuWithIfElse({ pizzas }) {
let content;
// Use if-else for complex logic (outside JSX)
if (pizzas.length === 0) {
content = <p>No pizzas available</p>;
} else if (pizzas.length < 3) {
content = (
<>
<p>Limited selection today</p>
<PizzaList pizzas={pizzas} />
</>
);
} else {
content = (
<>
<p>Full menu available!</p>
<PizzaList pizzas={pizzas} />
</>
);
}
// Then use the variable in JSX
return (
<main className="menu">
<h2>Our Menu</h2>
{content}
</main>
);
}
// Rule of thumb:
// - Simple either/or: Use ternary in JSX
// - Complex multi-branch: Use if-else before return
π React Usage Examples (Full Visual Guide!)
Complete React File: TernaryOperatorMasterClass.jsx
import React, { useState } from 'react';
// ==========================================
// INTERACTIVE TERNARY OPERATOR DEMO
// ==========================================
function TernaryOperatorMasterClass() {
const [activeTab, setActiveTab] = useState('basic');
const demos = {
basic: { title: 'Basic Ternary', component: <BasicTernaryDemo /> },
vsAnd: { title: 'Ternary vs &&', component: <VsAndDemo /> },
nested: { title: 'Nested Ternaries', component: <NestedTernaryDemo /> },
practical: { title: 'Real Examples', component: <PracticalDemo /> }
};
return (
<div style={{ maxWidth: '900px', margin: '0 auto', padding: '20px', fontFamily: 'Arial, sans-serif' }}>
<header style={{ background: '#2a9d8f', color: 'white', padding: '30px', borderRadius: '10px', marginBottom: '30px' }}>
<h1 style={{ margin: 0 }}>π Ternary Operator Master Class</h1>
<p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>The Either/Or Conditional Renderer</p>
</header>
<nav style={{ display: 'flex', gap: '10px', marginBottom: '30px', flexWrap: 'wrap' }}>
{Object.entries(demos).map(([key, { title }]) => (
<button
key={key}
onClick={() => setActiveTab(key)}
style={{
padding: '12px 24px',
fontSize: '16px',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
backgroundColor: activeTab === key ? '#264653' : '#e0e0e0',
color: activeTab === key ? 'white' : '#333',
fontWeight: activeTab === key ? 'bold' : 'normal'
}}
>
{title}
</button>
))}
</nav>
<main style={{ background: '#f8f9fa', padding: '30px', borderRadius: '10px', minHeight: '400px' }}>
{demos[activeTab].component}
</main>
</div>
);
}
// ==========================================
// DEMO 1: Basic Ternary Structure
// ==========================================
function BasicTernaryDemo() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [theme, setTheme] = useState('light');
return (
<div>
<h2>How Ternary Works</h2>
<div style={{ marginBottom: '20px', padding: '15px', background: '#e3f2fd', borderRadius: '8px' }}>
<code style={{ fontSize: '16px', background: 'white', padding: '10px', display: 'block', borderRadius: '4px' }}>
{'{condition ? <IfTrue /> : <IfFalse />}'}
</code>
<p style={{ margin: '10px 0 0 0', color: '#666' }}>
<strong>Three parts:</strong> Condition ? True Value : False Value
</p>
</div>
<div style={{ display: 'grid', gap: '15px' }}>
{/* Example 1: Login/Logout */}
<div style={{ padding: '15px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '10px' }}>
<button
onClick={() => setIsLoggedIn(!isLoggedIn)}
style={{ padding: '8px 16px', background: isLoggedIn ? '#f44336' : '#4caf50', color: 'white', border: 'none', borderRadius: '4px' }}
>
{isLoggedIn ? 'Log Out' : 'Log In'}
</button>
<span>isLoggedIn = {String(isLoggedIn)}</span>
</div>
<div style={{ padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
<code>{'{isLoggedIn ? <Welcome /> : <Login />}'}</code>
<div style={{ marginTop: '10px' }}>
{isLoggedIn ? (
<div style={{ padding: '10px', background: '#e8f5e9', borderRadius: '4px', color: '#2e7d32' }}>
π Welcome back, User!
</div>
) : (
<div style={{ padding: '10px', background: '#fff3e0', borderRadius: '4px' }}>
π Please log in to continue
</div>
)}
</div>
</div>
</div>
{/* Example 2: Theme Toggle */}
<div style={{ padding: '15px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '10px' }}>
<button
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
style={{ padding: '8px 16px', background: '#2196f3', color: 'white', border: 'none', borderRadius: '4px' }}
>
Toggle Theme
</button>
<span>theme = "{theme}"</span>
</div>
<div
style={{
padding: '20px',
borderRadius: '8px',
backgroundColor: theme === 'light' ? '#ffffff' : '#1a1a1a',
color: theme === 'light' ? '#333333' : '#ffffff',
border: `2px solid ${theme === 'light' ? '#ddd' : '#444'}`
}}
>
<h4 style={{ margin: '0 0 10px 0' }}>
{theme === 'light' ? 'βοΈ Light Mode' : 'π Dark Mode'}
</h4>
<p style={{ margin: 0 }}>
{theme === 'light'
? 'Bright and clean interface'
: 'Easy on the eyes at night'}
</p>
</div>
</div>
</div>
</div>
);
}
// ==========================================
// DEMO 2: Ternary vs && Comparison
// ==========================================
function VsAndDemo() {
const [hasPermission, setHasPermission] = useState(false);
const [showAlternative, setShowAlternative] = useState(false);
return (
<div>
<h2>&& vs Ternary: When to Use Which</h2>
<div style={{ marginBottom: '20px', display: 'flex', gap: '10px' }}>
<button
onClick={() => setHasPermission(!hasPermission)}
style={{ padding: '10px 20px', background: hasPermission ? '#4caf50' : '#f44336', color: 'white', border: 'none', borderRadius: '5px' }}
>
Permission: {String(hasPermission)}
</button>
<button
onClick={() => setShowAlternative(!showAlternative)}
style={{ padding: '10px 20px', background: '#2196f3', color: 'white', border: 'none', borderRadius: '5px' }}
>
Show Alternative: {String(showAlternative)}
</button>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}>
{/* && Operator */}
<div style={{ padding: '20px', background: '#ffebee', borderRadius: '8px', border: '2px solid #ef5350' }}>
<h3 style={{ color: '#c62828', marginTop: 0 }}>&& Operator</h3>
<code style={{ display: 'block', marginBottom: '15px', background: 'white', padding: '10px', borderRadius: '4px' }}>
{'{hasPermission && <Secret />}'}
</code>
<div style={{ padding: '15px', background: 'white', borderRadius: '4px', minHeight: '100px' }}>
{hasPermission && (
<div style={{ color: '#4caf50', fontWeight: 'bold' }}>π Secret Content Revealed!</div>
)}
{!hasPermission && (
<span style={{ color: '#999' }}>(Nothing shown - empty space)</span>
)}
</div>
<p style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
<strong>Use when:</strong> You want to show something OR nothing
</p>
</div>
{/* Ternary Operator */}
<div style={{ padding: '20px', background: '#e8f5e9', borderRadius: '8px', border: '2px solid #66bb6a' }}>
<h3 style={{ color: '#2e7d32', marginTop: 0 }}>Ternary Operator</h3>
<code style={{ display: 'block', marginBottom: '15px', background: 'white', padding: '10px', borderRadius: '4px' }}>
{'{hasPermission ? <Secret /> : <NoAccess />}'}
</code>
<div style={{ padding: '15px', background: 'white', borderRadius: '4px', minHeight: '100px' }}>
{hasPermission ? (
<div style={{ color: '#4caf50', fontWeight: 'bold' }}>π Secret Content Revealed!</div>
) : (
<div style={{ color: '#f44336' }}>π« Access Denied. Contact admin.</div>
)}
</div>
<p style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
<strong>Use when:</strong> You want to show A OR B (never nothing)
</p>
</div>
</div>
<div style={{ marginTop: '20px', padding: '15px', background: '#fff3e0', borderRadius: '8px' }}>
<strong>π‘ Rule of Thumb:</strong>
<ul style={{ margin: '10px 0 0 0' }}>
<li>Use <code>&&</code> for optional elements (badges, notifications)</li>
<li>Use <code>?:</code> for toggle states (login/logout, open/closed)</li>
</ul>
</div>
</div>
);
}
// ==========================================
// DEMO 3: Nested Ternaries (Advanced)
// ==========================================
function NestedTernaryDemo() {
const [status, setStatus] = useState('idle'); // idle, loading, success, error
return (
<div>
<h2>Multiple States with Ternary</h2>
<div style={{ marginBottom: '20px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
{['idle', 'loading', 'success', 'error'].map(s => (
<button
key={s}
onClick={() => setStatus(s)}
style={{
padding: '10px 20px',
background: status === s ? '#264653' : '#e0e0e0',
color: status === s ? 'white' : '#333',
border: 'none',
borderRadius: '5px',
textTransform: 'capitalize'
}}
>
{s}
</button>
))}
</div>
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h4>Code:</h4>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', overflow: 'auto' }}>
{`{
status === 'idle' ? (
<p>Ready to submit</p>
) : status === 'loading' ? (
<p>Loading...</p>
) : status === 'success' ? (
<p>β Success!</p>
) : (
<p>β Error occurred</p>
)
}`}
</pre>
<h4 style={{ marginTop: '20px' }}>Result:</h4>
<div style={{ padding: '20px', background: '#f5f5f5', borderRadius: '4px', minHeight: '60px' }}>
{status === 'idle' ? (
<p style={{ margin: 0, color: '#666' }}>Ready to submit</p>
) : status === 'loading' ? (
<p style={{ margin: 0, color: '#2196f3' }}>β³ Loading...</p>
) : status === 'success' ? (
<p style={{ margin: 0, color: '#4caf50', fontWeight: 'bold' }}>β Success!</p>
) : (
<p style={{ margin: 0, color: '#f44336', fontWeight: 'bold' }}>β Error occurred</p>
)}
</div>
</div>
<div style={{ marginTop: '20px', padding: '15px', background: '#ffebee', borderRadius: '8px' }}>
<strong>β οΈ Warning:</strong> Nested ternaries can be hard to read.
For complex logic, consider using a separate function or object mapping.
</div>
</div>
);
}
// ==========================================
// DEMO 4: Practical Real-World Examples
// ==========================================
function PracticalDemo() {
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const simulateLogin = () => {
setIsLoading(true);
setTimeout(() => {
setUser({ name: 'Alice', email: 'alice@example.com', isPremium: true });
setIsLoading(false);
}, 1500);
};
const logout = () => {
setUser(null);
};
return (
<div>
<h2>Real-World: Authentication Flow</h2>
<div style={{ marginBottom: '20px' }}>
{!user ? (
<button
onClick={simulateLogin}
disabled={isLoading}
style={{ padding: '10px 20px', background: '#4caf50', color: 'white', border: 'none', borderRadius: '5px' }}
>
{isLoading ? 'Logging in...' : 'Simulate Login'}
</button>
) : (
<button
onClick={logout}
style={{ padding: '10px 20px', background: '#f44336', color: 'white', border: 'none', borderRadius: '5px' }}
>
Log Out
</button>
)}
</div>
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0', minHeight: '200px' }}>
{isLoading ? (
<div style={{ textAlign: 'center', padding: '40px' }}>
<div style={{ fontSize: '40px' }}>β³</div>
<p>Authenticating...</p>
</div>
) : user ? (
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: '15px', marginBottom: '20px' }}>
<div style={{
width: '60px',
height: '60px',
borderRadius: '50%',
background: '#e76f51',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '24px',
color: 'white'
}}>
{user.name[0]}
</div>
<div>
<h3 style={{ margin: 0 }}>{user.name}</h3>
<p style={{ margin: '5px 0 0 0', color: '#666' }}>{user.email}</p>
</div>
{user.isPremium ? (
<span style={{
background: '#ffd700',
color: '#333',
padding: '4px 12px',
borderRadius: '12px',
fontSize: '12px',
fontWeight: 'bold'
}}>
β PREMIUM
</span>
) : (
<span style={{
background: '#e0e0e0',
color: '#666',
padding: '4px 12px',
borderRadius: '12px',
fontSize: '12px'
}}>
Free Plan
</span>
)}
</div>
<div style={{
padding: '15px',
background: user.isPremium ? '#fff8e1' : '#f5f5f5',
borderRadius: '8px',
border: `2px solid ${user.isPremium ? '#ffd700' : '#ddd'}`
}}>
<h4 style={{ margin: '0 0 10px 0' }}>
{user.isPremium ? 'Premium Features' : 'Upgrade to Premium'}
</h4>
<ul style={{ margin: 0, paddingLeft: '20px' }}>
<li style={{ textDecoration: user.isPremium ? 'none' : 'line-through', color: user.isPremium ? 'inherit' : '#999' }}>
Priority Support
</li>
<li style={{ textDecoration: user.isPremium ? 'none' : 'line-through', color: user.isPremium ? 'inherit' : '#999' }}>
Unlimited Storage
</li>
<li style={{ textDecoration: user.isPremium ? 'none' : 'line-through', color: user.isPremium ? 'inherit' : '#999' }}>
Advanced Analytics
</li>
</ul>
{!user.isPremium && (
<button style={{ marginTop: '10px', padding: '8px 16px', background: '#ffd700', border: 'none', borderRadius: '4px', fontWeight: 'bold' }}>
Upgrade Now
</button>
)}
</div>
</div>
) : (
<div style={{ textAlign: 'center', padding: '40px', color: '#666' }}>
<div style={{ fontSize: '40px' }}>π</div>
<p>Please log in to view your dashboard</p>
</div>
)}
</div>
</div>
);
}
export default TernaryOperatorMasterClass;
π§ Memory Aids for Poor Logic Thinking
Ternary Structure Card
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β TERNARY OPERATOR STRUCTURE β
β β
β BASIC PATTERN: β
β {condition ? <TrueComponent /> : <False />} β
β β
β THREE PARTS: β
β 1. CONDITION (must be true/false) β
β β β
β 2. ? (then) β
β β β
β 3. TRUE VALUE (if condition is true) β
β β β
β 4. : (else) β
β β β
β 5. FALSE VALUE (if condition is false) β
β β
β VISUAL RAILROAD TRACK: β
β β
β TRUE β
β β β
β CONDITION ? <A /> : <B /> β
β β β β
β false false β
β β β
β Shows B β
β β
β COMPARISON WITH IF-ELSE: β
β βββββββββββββββββββ¬ββββββββββββββββββββββββββ β
β β if (x) { β x ? β β
β β return A; β <A /> β β
β β } else { β : β β
β β return B; β <B /> β β
β β } β β β
β β β β β
β β STATEMENT β EXPRESSION β β
β β (No value) β (Returns value) β β
β β Can't use in {} β Can use in {} β β
β βββββββββββββββββββ΄ββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
&& vs Ternary Decision Tree
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β SHOULD I USE && OR TERNARY? β
β β
β Do you want to show NOTHING when false? β
β β YES β
β Use &&: {condition && <Component />} β
β Example: {hasNotifications && <Badge />} β
β β NO (you want alternative when false) β
β Use Ternary: {condition ? <A /> : <B />} β
β Example: {isOpen ? <Open /> : <Closed />} β
β β
β QUICK REFERENCE TABLE: β
β βββββββββββββββββββ¬ββββββββββββββββββββββββββ β
β β && OPERATOR β TERNARY OPERATOR β β
β βββββββββββββββββββΌββββββββββββββββββββββββββ€ β
β β Show or Hide β This or That β β
β β All or Nothing β Either/Or β β
β β One outcome β Two outcomes β β
β βββββββββββββββββββΌββββββββββββββββββββββββββ€ β
β β {isAdmin && β {isAdmin ? β β
β β <AdminPanel />β <AdminPanel /> : β β
β β } β <UserPanel /> β β
β β β } β β
β βββββββββββββββββββΌββββββββββββββββββββββββββ€ β
β β Good for: β Good for: β β
β β β’ Badges β β’ Toggle states β β
β β β’ Notifications β β’ Login/Logout β β
β β β’ Optional UI β β’ Loading/Error/Data β β
β β β’ Extra features β β’ Theme switching β β
β βββββββββββββββββββ΄ββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
Common Ternary Patterns
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β COMMON TERNARY PATTERNS (Copy These!) β
β β
β AUTHENTICATION: β
β {user ? <Dashboard /> : <Login />} β
β β
β LOADING STATES: β
β {isLoading ? <Spinner /> : <Content />} β
β β
β ERROR HANDLING: β
β {error ? <ErrorMessage /> : <Data />} β
β β
β EMPTY STATES: β
β {items.length > 0 ? <List /> : <Empty />} β
β β
β THEME TOGGLE: β
β {theme === 'dark' ? <DarkMode /> : <Light />} β
β β
β ACCESS CONTROL: β
β {hasPermission ? <Secret /> : <Denied />} β
β β
β STYLING: β
β className={isActive ? 'active' : 'inactive'} β
β β
β TEXT CONTENT: β
β {isOpen ? 'Close' : 'Open'} β
β β
β MULTIPLE STATES: β
β {status === 'loading' ? <Loading /> : β
β status === 'error' ? <Error /> : β
β status === 'success' ? <Success /> : β
β <Idle />} β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
If-Else vs Ternary Guide
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β IF-ELSE vs TERNARY: WHERE TO USE β
β β
β β CANNOT use if-else INSIDE JSX: β
β βββββββββββββββββββββββββββββββββββββββ β
β β // Inside return() β β
β β { β β
β β if (x) { // β ERROR! β β
β β return <A />; β β
β β } else { β β
β β return <B />; β β
β β } β β
β β } β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β β
CAN use if-else BEFORE return: β
β βββββββββββββββββββββββββββββββββββββββ β
β β function Component() { β β
β β let content; β β
β β β β
β β if (x) { β β
β β content = <A />; β β
β β } else { β β
β β content = <B />; β β
β β } β β
β β β β
β β return ( β β
β β <div>{content}</div> β β
β β ); β β
β β } β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β β
USE TERNARY for simple INSIDE JSX: β
β βββββββββββββββββββββββββββββββββββββββ β
β β return ( β β
β β <div> β β
β β {x ? <A /> : <B />} β β
β β </div> β β
β β ); β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β RULE OF THUMB: β
β β’ Simple either/or inside JSX β Ternary β
β β’ Complex logic with many branches β If-else β
β before return β
β β’ Optional content (show or hide) β && β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
π Practice Exercises
Exercise 1: Convert && to Ternary
These use && but should use ternary for better UX. Convert them:
// BEFORE (using && - shows nothing when false):
function StatusBefore({ status }) {
return (
<div>
{status === 'loading' && <p>Loading...</p>}
{status === 'success' && <p>Done!</p>}
{status === 'error' && <p>Error!</p>}
</div>
);
}
// TODO: AFTER (using ternary - always shows something):
function StatusAfter({ status }) {
return (
<div>
{/* Use single ternary chain */}
</div>
);
}
Solution:
function StatusAfter({ status }) {
return (
<div>
{status === 'loading' ? (
<p style={{ color: '#2196f3' }}>β³ Loading...</p>
) : status === 'success' ? (
<p style={{ color: '#4caf50' }}>β Done!</p>
) : status === 'error' ? (
<p style={{ color: '#f44336' }}>β Error!</p>
) : (
<p style={{ color: '#999' }}>Waiting...</p>
)}
</div>
);
}
Exercise 2: Build a Toggle Component
Create a component that switches between two views:
// TODO: Create ViewToggle component
// Props: defaultView ('list' or 'grid'), items (array)
// Show list view or grid view based on state
// Include button to toggle between views
function ViewToggle({ defaultView = 'list', items }) {
// TODO: State for current view
return (
<div>
{/* TODO: Toggle button */}
{/* TODO: Ternary to show ListView or GridView */}
</div>
);
}
Solution:
import { useState } from 'react';
function ViewToggle({ defaultView = 'list', items }) {
const [view, setView] = useState(defaultView);
return (
<div>
<div style={{ marginBottom: '20px' }}>
<button
onClick={() => setView('list')}
style={{
padding: '10px 20px',
background: view === 'list' ? '#264653' : '#e0e0e0',
color: view === 'list' ? 'white' : '#333',
border: 'none',
borderRadius: '5px 0 0 5px'
}}
>
π List
</button>
<button
onClick={() => setView('grid')}
style={{
padding: '10px 20px',
background: view === 'grid' ? '#264653' : '#e0e0e0',
color: view === 'grid' ? 'white' : '#333',
border: 'none',
borderRadius: '0 5px 5px 0'
}}
>
β Grid
</button>
</div>
{view === 'list' ? (
<ul style={{ listStyle: 'none', padding: 0 }}>
{items.map((item, index) => (
<li
key={index}
style={{
padding: '15px',
marginBottom: '10px',
background: '#f5f5f5',
borderRadius: '8px',
display: 'flex',
alignItems: 'center',
gap: '15px'
}}
>
<span style={{ fontSize: '24px' }}>{item.icon}</span>
<div>
<h4 style={{ margin: 0 }}>{item.title}</h4>
<p style={{ margin: '5px 0 0 0', color: '#666' }}>{item.description}</p>
</div>
</li>
))}
</ul>
) : (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: '15px' }}>
{items.map((item, index) => (
<div
key={index}
style={{
padding: '20px',
background: '#f5f5f5',
borderRadius: '8px',
textAlign: 'center'
}}
>
<span style={{ fontSize: '40px' }}>{item.icon}</span>
<h4 style={{ margin: '10px 0 5px 0' }}>{item.title}</h4>
<p style={{ margin: 0, color: '#666', fontSize: '14px' }}>{item.description}</p>
</div>
))}
</div>
)}
</div>
);
}
// Usage:
// <ViewToggle
// items={[
// { icon: 'π±', title: 'Mobile', description: 'iOS & Android' },
// { icon: 'π»', title: 'Desktop', description: 'Windows & Mac' },
// { icon: 'π', title: 'Web', description: 'All browsers' }
// ]}
// />
Exercise 3: Fix the Nested Ternary
This code works but is hard to read. Refactor it:
function MessyStatus({ status, count, user }) {
return (
<div>
{status === 'loading' ? (
<p>Loading...</p>
) : status === 'error' ? (
<p>Error!</p>
) : status === 'success' ? (
count > 0 ? (
user ? (
<p>Welcome back, {user.name}! You have {count} messages.</p>
) : (
<p>You have {count} messages. Please log in.</p>
)
) : (
<p>No messages.</p>
)
) : (
<p>Unknown status.</p>
)}
</div>
);
}
Solution:
function CleanStatus({ status, count, user }) {
// Extract complex logic into separate function
const getMessageContent = () => {
if (count === 0) return <p>No messages.</p>;
if (user) {
return <p>Welcome back, {user.name}! You have {count} messages.</p>;
}
return <p>You have {count} messages. Please log in.</p>;
};
// Simpler ternary for top-level status
return (
<div>
{status === 'loading' && <p>Loading...</p>}
{status === 'error' && <p>Error!</p>}
{status === 'success' && getMessageContent()}
{status !== 'loading' && status !== 'error' && status !== 'success' && (
<p>Unknown status.</p>
)}
</div>
);
}
// Even cleaner with object mapping:
function CleanestStatus({ status, count, user }) {
const statusComponents = {
loading: <p>Loading...</p>,
error: <p>Error!</p>,
success: <SuccessContent count={count} user={user} />
};
return (
<div>
{statusComponents[status] || <p>Unknown status.</p>}
</div>
);
}
function SuccessContent({ count, user }) {
if (count === 0) return <p>No messages.</p>;
if (user) return <p>Welcome back, {user.name}! You have {count} messages.</p>;
return <p>You have {count} messages. Please log in.</p>;
}
π‘ Key Takeaways
| Concept | What It Means | Example |
|---|---|---|
| Ternary Operator | Compact if-else expression | condition ? A : B |
| Three Parts | Condition, True value, False value | isOpen ? <Open /> : <Closed /> |
| vs && Operator | Ternary shows alternative, && shows nothing | Use ternary for Either/Or |
| vs If-Else | Ternary is expression (can use in JSX), if-else is statement | Use if-else before return for complex logic |
| Nested Ternaries | Can chain but hard to read | Keep simple or extract to function |
The Ternary Pattern:
{condition ? <ComponentIfTrue /> : <ComponentIfFalse />}
When to Use What:
- &&: Optional content (show badge or nothing)
- Ternary: Toggle content (show A or B)
- If-else: Complex logic before return statement
Common Mistakes:
- β Forgetting the
:part - β Using if-else inside JSX {}
- β Over-nesting ternaries (hard to read)
- β Using ternary when && is cleaner
One Sentence Summary: > "Use the ternary operator condition ? <A /> : <B /> when you want to show one of two things based on a condition inside JSX β it's a compact if-else that produces a value, unlike the if-else statement which cannot be used inside curly braces!"