π― What Are Conditional Text & Classes? (Simple Analogy)
Imagine you're a shop owner changing your store display:
STATIC DISPLAY (What you learned before):
βββββββββββββββββββββββββββββββββββββββββββ
βΒ πͺ SHOP WINDOWΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ Every day looks the same:Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ βββββββββββββββββββββββββββββββββββΒ Β Β β
βΒ βΒ π Pizza: $12Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β βΒ Β Β β
βΒ βΒ Status: AVAILABLEΒ Β Β Β Β Β Β Β Β Β Β Β Β Β βΒ Β Β β
βΒ βΒ Color: Normal (green border)Β Β Β βΒ Β Β β
βΒ βββββββββββββββββββββββββββββββββββΒ Β Β β
βΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ Problem: Even when sold out,Β Β Β Β Β Β Β Β Β Β β
βΒ it still shows "$12" and "AVAILABLE"Β Β β
βΒ and looks the same!Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ In React:Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ <li className="pizza">Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ Β Β <span>$12</span>Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ </li>Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ // Always the same, no matter what!Β Β Β β
βββββββββββββββββββββββββββββββββββββββββββ
CONDITIONAL DISPLAY (New technique):
βββββββββββββββββββββββββββββββββββββββββββ
βΒ πͺ SMART SHOP WINDOWΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ When IN STOCK:Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ βββββββββββββββββββββββββββββββββββΒ Β Β β
βΒ βΒ π Pizza: $12Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β βΒ Β Β β
βΒ βΒ Status: AVAILABLEΒ Β Β Β Β Β Β Β Β Β Β Β Β Β βΒ Β Β β
βΒ βΒ Color: Normal (green border)Β Β Β βΒ Β Β β
βΒ βββββββββββββββββββββββββββββββββββΒ Β Β β
βΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ When SOLD OUT:Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ βββββββββββββββββββββββββββββββββββΒ Β Β β
βΒ βΒ π Pizza: SOLD OUTΒ Β Β Β Β Β Β Β Β Β Β Β Β βΒ Β Β β
βΒ βΒ Status: UNAVAILABLEΒ Β Β Β Β Β Β Β Β Β Β Β βΒ Β Β β
βΒ βΒ Color: Grayed out (gray border) βΒ Β Β β
βΒ βββββββββββββββββββββββββββββββββββΒ Β Β β
βΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ Same element, different content & style!β
βΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ In React:Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ <li className={soldOut ? "pizza sold-out" : "pizza"}> β
βΒ Β Β <span>{soldOut ? "SOLD OUT" : "$12"}</span>Β Β Β Β Β Β Β Β β
βΒ </li>Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β β
βΒ // Changes based on condition!Β Β Β Β Β Β Β Β β
βββββββββββββββββββββββββββββββββββββββββββ
KEY INSIGHT:
Conditional text = "Same box, different label"
Conditional class = "Same box, different paint"
β οΈ The Big Problem: "How Do I Change Just Part of an Element?"
// ==========================================
// THE "ALL OR NOTHING" TRAP (Review)
// ==========================================
// β WRONG: Hiding the entire pizza when sold out
function Pizza({ pizzaObj }) {
if (pizzaObj.soldOut) return null; // Pizza disappears completely!
return (
<li className="pizza">
<img src={pizzaObj.photoName} alt={pizzaObj.name} />
<div>
<h3>{pizzaObj.name}</h3>
<p>{pizzaObj.ingredients}</p>
<span>${pizzaObj.price}</span>
</div>
</li>
);
}
// Problem: We want to SHOW the pizza but gray it out
// We want to say "SOLD OUT" instead of the price
// But we still want the image, name, and ingredients visible!
// ==========================================
// THE SOLUTION: Change content INSIDE the element
// ==========================================
// β
CORRECT: Keep the element, change its content
function Pizza({ pizzaObj }) {
return (
<li className={`pizza ${pizzaObj.soldOut ? "sold-out" : ""}`}>
<img src={pizzaObj.photoName} alt={pizzaObj.name} />
<div>
<h3>{pizzaObj.name}</h3>
<p>{pizzaObj.ingredients}</p>
{/* Change just the text, not the whole element! */}
<span>{pizzaObj.soldOut ? "SOLD OUT" : `$${pizzaObj.price}`}</span>
</div>
</li>
);
}
// Visual comparison:
// Before: After:
// Pizza disappears Pizza stays visible
// β β
// Bad UX! Good UX!
// User doesn't know User knows it's sold out
// what existed but can still see it
π Complete Basic Examples
Create file: react-conditional-text-classes.js
// ==========================================
// CONDITIONAL TEXT & CLASSES - Complete Guide
// ==========================================
/*
TWO TECHNIQUES:
βββββββββββββββββββββββββββββββββββββββββββ
β 1. CONDITIONAL TEXT CONTENT β
β Change what's inside an element β
β {condition ? "Text A" : "Text B"} β
β β
β 2. CONDITIONAL CSS CLASSES β
β Change the styling of an element β
β className={condition ? "class-a" : "class-b"} β
βββββββββββββββββββββββββββββββββββββββββββ
*/
// ==========================================
// EXAMPLE 1: Conditional Text (Pizza Price)
// ==========================================
function Pizza({ pizzaObj }) {
return (
<li className="pizza">
<img src={pizzaObj.photoName} alt={pizzaObj.name} />
<div>
<h3>{pizzaObj.name}</h3>
<p>{pizzaObj.ingredients}</p>
{/* CONDITIONAL TEXT: Price or "SOLD OUT" */}
<span>
{pizzaObj.soldOut
? "SOLD OUT" // If sold out, show this text
: `$${pizzaObj.price}` // If not, show the price
}
</span>
</div>
</li>
);
}
// Visual Flow:
// pizzaObj.soldOut = true
// β
// Ternary checks: true ?
// β
// Returns "SOLD OUT"
// β
// <span>SOLD OUT</span>
// pizzaObj.soldOut = false
// β
// Ternary checks: false ?
// β
// Returns `$${pizzaObj.price}` β "$12"
// β
// <span>$12</span>
// ==========================================
// EXAMPLE 2: Conditional CSS Classes (Grayed Out)
// ==========================================
function Pizza({ pizzaObj }) {
return (
{/* CONDITIONAL CLASS: Add "sold-out" if soldOut is true */}
<li className={`pizza ${pizzaObj.soldOut ? "sold-out" : ""}`}>
<img src={pizzaObj.photoName} alt={pizzaObj.name} />
<div>
<h3>{pizzaObj.name}</h3>
<p>{pizzaObj.ingredients}</p>
<span>{pizzaObj.soldOut ? "SOLD OUT" : `$${pizzaObj.price}`}</span>
</div>
</li>
);
}
// CSS:
// .pizza { border: 2px solid green; opacity: 1; }
// .pizza.sold-out { border: 2px solid gray; opacity: 0.5; }
// Visual Flow:
// pizzaObj.soldOut = true
// β
// Template literal: `pizza ${true ? "sold-out" : ""}`
// β
// Result: "pizza sold-out"
// β
// <li className="pizza sold-out"> β Grayed out!
// pizzaObj.soldOut = false
// β
// Template literal: `pizza ${false ? "sold-out" : ""}`
// β
// Result: "pizza " (just "pizza" with trailing space)
// β
// <li className="pizza"> β Normal!
// ==========================================
// EXAMPLE 3: The Template Literal Explained
// ==========================================
// What is a template literal?
// It's a string that can contain JavaScript!
const name = "Alice";
const greeting = `Hello ${name}!`; // "Hello Alice!"
// In JSX for classes:
const soldOut = true;
const className = `pizza ${soldOut ? "sold-out" : ""}`;
// Result: "pizza sold-out"
const soldOut = false;
const className = `pizza ${soldOut ? "sold-out" : ""}`;
// Result: "pizza "
// Visual:
// `pizza ${condition ? "sold-out" : ""}`
// β β
// Static text Dynamic part (JavaScript!)
// ==========================================
// EXAMPLE 4: Restaurant Open Status
// ==========================================
function Footer({ hour, openHour, closeHour }) {
const isOpen = hour >= openHour && hour <= closeHour;
return (
<footer className={`footer ${isOpen ? "open" : "closed"}`}>
{/* Conditional text in heading */}
<h2>
{isOpen
? "π’ We're Open!"
: "π΄ We're Closed"
}
</h2>
{/* Conditional text in paragraph */}
<p>
{isOpen
? `Come visit us! Open until ${closeHour}:00`
: `Sorry, we're closed. We open at ${openHour}:00`
}
</p>
{/* Conditional button text */}
<button className={`btn ${isOpen ? "btn-active" : "btn-disabled"}`}>
{isOpen ? "Order Now" : "View Menu"}
</button>
</footer>
);
}
// CSS:
// .footer.open { background: #e8f5e9; border-color: #4caf50; }
// .footer.closed { background: #ffebee; border-color: #f44336; }
// .btn-active { background: #4caf50; cursor: pointer; }
// .btn-disabled { background: #ccc; cursor: not-allowed; }
// ==========================================
// EXAMPLE 5: User Status Badge
// ==========================================
function UserCard({ user }) {
return (
<div className={`user-card ${user.isAdmin ? "admin" : "regular"}`}>
<img src={user.avatar} alt={user.name} />
<h3>{user.name}</h3>
{/* Conditional badge text and class */}
<span className={`badge ${user.isAdmin ? "badge-admin" : "badge-user"}`}>
{user.isAdmin ? "π ADMIN" : "π€ USER"}
</span>
{/* Conditional status text */}
<p className={`status ${user.isOnline ? "online" : "offline"}`}>
{user.isOnline ? "π’ Online" : "β« Offline"}
</p>
</div>
);
}
// ==========================================
// EXAMPLE 6: Form Input States
// ==========================================
function InputField({ label, value, error, isValid }) {
return (
<div className="form-group">
<label>{label}</label>
<input
className={`input ${error ? "input-error" : isValid ? "input-success" : ""}`}
value={value}
/>
{/* Conditional helper text */}
<span className={`helper-text ${error ? "text-error" : "text-hint"}`}>
{error ? `β ${error}` : "β Looks good!"}
</span>
</div>
);
}
// Usage:
// <InputField label="Email" value=alice@email.com isValid={true} />
// β Green border, "β Looks good!"
// <InputField label="Email" value="invalid" error="Invalid email format" />
// β Red border, "β Invalid email format"
π Interactive React Usage Examples
Complete React File: ConditionalTextClassesMasterClass.jsx
import React, { useState } from 'react';
// ==========================================
// INTERACTIVE CONDITIONAL TEXT & CLASSES DEMO
// ==========================================
function ConditionalTextClassesMasterClass() {
const [demo, setDemo] = useState('text');
const demos = {
text: { title: 'Conditional Text', component: <TextDemo /> },
classes: { title: 'Conditional Classes', component: <ClassesDemo /> },
combined: { title: 'Combined', component: <CombinedDemo /> },
comparison: { title: 'vs Element Rendering', component: <ComparisonDemo /> }
};
return (
<div style={{ maxWidth: '900px', margin: '0 auto', padding: '20px', fontFamily: 'Arial, sans-serif' }}>
<header style={{ background: '#e9c46a', color: '#264653', padding: '30px', borderRadius: '10px', marginBottom: '30px' }}>
<h1 style={{ margin: 0 }}>π¨ Conditional Text & Classes</h1>
<p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>Changing Content & Style Inside Elements</p>
</header>
<nav style={{ display: 'flex', gap: '10px', marginBottom: '30px', flexWrap: 'wrap' }}>
{Object.entries(demos).map(([key, { title }]) => (
<button
key={key}
onClick={() => setDemo(key)}
style={{
padding: '12px 24px',
fontSize: '16px',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
backgroundColor: demo === key ? '#264653' : '#e0e0e0',
color: demo === key ? 'white' : '#333',
fontWeight: demo === key ? 'bold' : 'normal'
}}
>
{title}
</button>
))}
</nav>
<main style={{ background: '#f8f9fa', padding: '30px', borderRadius: '10px', minHeight: '400px' }}>
{demos[demo].component}
</main>
</div>
);
}
// ==========================================
// DEMO 1: Conditional Text Content
// ==========================================
function TextDemo() {
const [soldOut, setSoldOut] = useState(false);
const pizza = {
name: "Margherita",
price: 12,
ingredients: "Tomato, mozzarella, basil",
soldOut: soldOut
};
return (
<div>
<h2>Conditional Text: Price vs "SOLD OUT"</h2>
<div style={{ marginBottom: '20px' }}>
<button
onClick={() => setSoldOut(!soldOut)}
style={{
padding: '12px 24px',
fontSize: '16px',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
backgroundColor: soldOut ? '#f44336' : '#4caf50',
color: 'white'
}}
>
Toggle: {soldOut ? 'SOLD OUT' : 'IN STOCK'}
</button>
</div>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
{/* Code Example */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Code:</h3>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px', overflow: 'auto' }}>
{`<span>
{pizzaObj.soldOut
? "SOLD OUT"
: \`$\${pizzaObj.price}\`
}
</span>`}
</pre>
<div style={{ marginTop: '15px', padding: '15px', background: '#f5f5f5', borderRadius: '4px' }}>
<h4>How it works:</h4>
<ul>
<li>Keep the <code><span></code> element</li>
<li>Only change the TEXT inside</li>
<li>Use ternary: condition ? "A" : "B"</li>
</ul>
</div>
</div>
{/* Live Result */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Result:</h3>
<div style={{ padding: '20px', background: '#f5f5f5', borderRadius: '8px' }}>
<div style={{ display: 'flex', gap: '15px', alignItems: 'center' }}>
<div style={{ fontSize: '40px' }}>π</div>
<div>
<h4 style={{ margin: '0 0 5px 0' }}>{pizza.name}</h4>
<p style={{ margin: '0 0 10px 0', color: '#666' }}>{pizza.ingredients}</p>
<span style={{
fontWeight: 'bold',
fontSize: '18px',
color: soldOut ? '#f44336' : '#2a9d8f'
}}>
{soldOut ? "SOLD OUT" : `$${pizza.price}`}
</span>
</div>
</div>
</div>
<div style={{ marginTop: '15px', padding: '10px', background: soldOut ? '#ffebee' : '#e8f5e9', borderRadius: '4px' }}>
<strong>Current state:</strong> {soldOut ? 'Showing "SOLD OUT"' : `Showing "$${pizza.price}"`}
</div>
</div>
</div>
</div>
);
}
// ==========================================
// DEMO 2: Conditional CSS Classes
// ==========================================
function ClassesDemo() {
const [soldOut, setSoldOut] = useState(false);
return (
<div>
<h2>Conditional Classes: Normal vs Grayed Out</h2>
<div style={{ marginBottom: '20px' }}>
<button
onClick={() => setSoldOut(!soldOut)}
style={{
padding: '12px 24px',
fontSize: '16px',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
backgroundColor: soldOut ? '#f44336' : '#4caf50',
color: 'white'
}}
>
Toggle Style: {soldOut ? 'SOLD OUT' : 'IN STOCK'}
</button>
</div>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
{/* Code Example */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Code:</h3>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px', overflow: 'auto' }}>
{`<li className={\`pizza \${pizzaObj.soldOut ? "sold-out" : ""}\`}>
{/* content */}
</li>`}
</pre>
<div style={{ marginTop: '15px', padding: '15px', background: '#f5f5f5', borderRadius: '4px' }}>
<h4>Template Literal Breakdown:</h4>
<p><code>`pizza ${soldOut ? "sold-out" : ""}`</code></p>
<ul>
<li><strong>soldOut = true:</strong> "pizza sold-out"</li>
<li><strong>soldOut = false:</strong> "pizza "</li>
</ul>
</div>
</div>
{/* Live Result */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Result:</h3>
<div
style={{
padding: '20px',
borderRadius: '8px',
border: '2px solid',
borderColor: soldOut ? '#9e9e9e' : '#4caf50',
backgroundColor: soldOut ? '#f5f5f5' : 'white',
opacity: soldOut ? 0.6 : 1,
transition: 'all 0.3s ease'
}}
>
<div style={{ display: 'flex', gap: '15px', alignItems: 'center' }}>
<div style={{ fontSize: '40px', filter: soldOut ? 'grayscale(100%)' : 'none' }}>π</div>
<div>
<h4 style={{ margin: '0 0 5px 0', color: soldOut ? '#666' : '#333' }}>Margherita</h4>
<p style={{ margin: '0 0 10px 0', color: soldOut ? '#999' : '#666' }}>Tomato, mozzarella, basil</p>
<span style={{
fontWeight: 'bold',
fontSize: '18px',
color: soldOut ? '#f44336' : '#2a9d8f'
}}>
{soldOut ? "SOLD OUT" : "$12"}
</span>
</div>
</div>
</div>
<div style={{ marginTop: '15px', padding: '10px', background: '#fff3e0', borderRadius: '4px', fontSize: '14px' }}>
<strong>Applied classes:</strong><br/>
{soldOut ? '"pizza sold-out"' : '"pizza"'}<br/>
<em>(Grayed out, reduced opacity)</em>
</div>
</div>
</div>
</div>
);
}
// ==========================================
// DEMO 3: Combined Text + Classes
// ==========================================
function CombinedDemo() {
const [status, setStatus] = useState('loading'); // loading, error, success
const statuses = {
loading: { label: 'Loading', color: '#2196f3', icon: 'β³' },
error: { label: 'Error', color: '#f44336', icon: 'β' },
success: { label: 'Success', color: '#4caf50', icon: 'β
' }
};
const current = statuses[status];
return (
<div>
<h2>Combined: Status Badge</h2>
<div style={{ marginBottom: '20px', display: 'flex', gap: '10px' }}>
{['loading', 'error', 'success'].map(s => (
<button
key={s}
onClick={() => setStatus(s)}
style={{
padding: '10px 20px',
background: status === s ? current.color : '#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' }}>
<h3>Full Component:</h3>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px', overflow: 'auto' }}>
{`function StatusBadge({ status }) {
return (
<div className={\`badge \${status}\`}>
<span className="icon">
{status === 'loading' ? 'β³' :
status === 'error' ? 'β' : 'β
'}
</span>
<span className="text">
{status === 'loading' ? 'Loading...' :
status === 'error' ? 'Error occurred' : 'Success!'}
</span>
</div>
);
}`}
</pre>
<h3 style={{ marginTop: '20px' }}>Live Result:</h3>
<div
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '10px',
padding: '15px 25px',
borderRadius: '8px',
backgroundColor: current.color + '20', // 20 = hex opacity
border: `2px solid ${current.color}`,
color: current.color
}}
>
<span style={{ fontSize: '24px' }}>{current.icon}</span>
<span style={{ fontWeight: 'bold', fontSize: '18px' }}>
{status === 'loading' ? 'Loading...' :
status === 'error' ? 'Error occurred' : 'Success!'}
</span>
</div>
</div>
</div>
);
}
// ==========================================
// DEMO 4: Comparison with Element Rendering
// ==========================================
function ComparisonDemo() {
const [soldOut, setSoldOut] = useState(false);
return (
<div>
<h2>Method Comparison: Same Result, Different Approach</h2>
<div style={{ marginBottom: '20px' }}>
<button
onClick={() => setSoldOut(!soldOut)}
style={{
padding: '12px 24px',
fontSize: '16px',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
backgroundColor: soldOut ? '#f44336' : '#4caf50',
color: 'white'
}}
>
Toggle: {soldOut ? 'SOLD OUT' : 'IN STOCK'}
</button>
</div>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
{/* Method 1: Conditional Element */}
<div style={{ padding: '20px', background: '#ffebee', borderRadius: '8px' }}>
<h3 style={{ color: '#c62828', marginTop: 0 }}>β Method 1: Conditional Element</h3>
<p style={{ fontSize: '14px', color: '#666' }}>
Change the ENTIRE element based on condition
</p>
<pre style={{ background: 'white', padding: '10px', borderRadius: '4px', fontSize: '12px' }}>
{`{soldOut ? (
<span className="sold-out-text">
SOLD OUT
</span>
) : (
<span className="price-text">
$12
</span>
)}`}
</pre>
<div style={{ marginTop: '10px', padding: '15px', background: 'white', borderRadius: '4px' }}>
{soldOut ? (
<span style={{ color: '#f44336', fontWeight: 'bold' }}>SOLD OUT</span>
) : (
<span style={{ color: '#2a9d8f', fontWeight: 'bold' }}>$12</span>
)}
</div>
<p style={{ fontSize: '13px', color: '#666', marginTop: '10px' }}>
<em>Problem: Duplicated <span> element. What if you need to change the tag later?</em>
</p>
</div>
{/* Method 2: Conditional Text */}
<div style={{ padding: '20px', background: '#e8f5e9', borderRadius: '8px' }}>
<h3 style={{ color: '#2e7d32', marginTop: 0 }}>β
Method 2: Conditional Text (Better!)</h3>
<p style={{ fontSize: '14px', color: '#666' }}>
Keep the element, change only the CONTENT
</p>
<pre style={{ background: 'white', padding: '10px', borderRadius: '4px', fontSize: '12px' }}>
{`<span className={soldOut ? "sold-out" : "price"}>
{soldOut ? "SOLD OUT" : "$12"}
</span>`}
</pre>
<div style={{ marginTop: '10px', padding: '15px', background: 'white', borderRadius: '4px' }}>
<span style={{
color: soldOut ? '#f44336' : '#2a9d8f',
fontWeight: 'bold'
}}>
{soldOut ? "SOLD OUT" : "$12"}
</span>
</div>
<p style={{ fontSize: '13px', color: '#666', marginTop: '10px' }}>
<em>Better: One <span>, dynamic content. Cleaner and more maintainable!</em>
</p>
</div>
</div>
<div style={{ marginTop: '20px', padding: '15px', background: '#fff3e0', borderRadius: '8px' }}>
<h4>π‘ When to Use Which:</h4>
<ul style={{ margin: '10px 0 0 0' }}>
<li><strong>Conditional Element:</strong> Completely different HTML structure</li>
<li><strong>Conditional Text:</strong> Same element, different content (preferred!)</li>
</ul>
</div>
</div>
);
}
export default ConditionalTextClassesMasterClass;
π§ Memory Aids for Poor Logic Thinking
The "Chameleon" Analogy
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β CONDITIONAL TEXT & CLASSES = CHAMELEON π¦ β
β β
β A chameleon changes color based on environment β
β but it's still the SAME chameleon! β
β β
β BEFORE (Replacing the whole animal): β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β if (danger) return <RedLizard />; β β
β β return <GreenLizard />; β β
β β β β
β β Problem: Two different animals! β β
β β What if we want to add legs? β β
β β Need to change BOTH components! β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β AFTER (Same animal, different color): β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β <Lizard color={danger ? "red" : β β
β β "green"} /> β β
β β β β
β β Same component! Just props change. β β
β β Add legs in ONE place. β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β IN REACT: β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β // Same element, different text β β
β β <span> β β
β β {soldOut ? "SOLD OUT" : "$12"} β β
β β </span> β β
β β β β
β β // Same element, different class β β
β β <li className={\`pizza \${soldOut ? β β
β β "sold-out" : ""}\`}> β β
β βββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
Template Literal Visual Breakdown
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β TEMPLATE LITERAL FOR CLASSES - STEP BY STEP β
β β
β GOAL: Create class string based on condition β
β β
β Step 1: Start with backticks ` ` β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β `pizza ` β β
β β β β β
β β Static text "pizza " (with space) β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β β
β Step 2: Add dynamic part with ${ } β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β `pizza ${condition ? "sold-out" : ""}` β β
β β β β β
β β JavaScript expression! β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β β
β Step 3: Evaluate based on condition β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β If soldOut = true: β β
β β `pizza ${"sold-out"}` β β
β β β "pizza sold-out" β β
β β β β
β β If soldOut = false: β β
β β `pizza ${""}` β β
β β β "pizza " β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β REMEMBER: β
β β’ Backticks ` ` NOT quotes ' ' or " " β
β β’ ${ } for JavaScript inside string β
β β’ Condition ? "if-true" : "if-false" β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
Common Patterns Cheat Sheet
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β COMMON CONDITIONAL PATTERNS β
β β
β 1. TEXT CONTENT: β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β <span> β β
β β {isOpen ? "Open" : "Closed"} β β
β β </span> β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β 2. CSS CLASS (Simple): β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β <div className={isActive ? "active" : β β
β β "inactive"}> β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β 3. CSS CLASS (Combined): β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β <div className={\`card \${isActive ? β β
β β "active" : ""}\`}> β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β 4. MULTIPLE CLASSES: β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β <div className={\`btn \${isLarge ? β β
β β "btn-lg" : ""} \${isPrimary ? β β
β β "btn-primary" : "btn-secondary"}\`}> β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β 5. STYLE OBJECT (Inline): β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β <div style={{ β β
β β color: isError ? 'red' : 'green', β β
β β opacity: isLoading ? 0.5 : 1 β β
β β }}> β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β 6. CONDITIONAL ATTRIBUTE: β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β <button disabled={!isValid}> β β
β β <input readOnly={isLocked} /> β β
β βββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
π Practice Exercises
Exercise 1: Convert to Conditional Text
Convert this to use conditional text instead of conditional elements:
function Status({ isOnline }) {
return (
<div>
{isOnline ? (
<span className="online">Online</span>
) : (
<span className="offline">Offline</span>
)}
</div>
);
}
Solution:
function Status({ isOnline }) {
return (
<div>
{/* Same element, conditional class and text */}
<span className={isOnline ? "online" : "offline"}>
{isOnline ? "Online" : "Offline"}
</span>
</div>
);
}
Exercise 2: Create a Product Card
Create a product card that shows "SALE" badge and discounted price when on sale:
function ProductCard({ product }) {
// TODO: Add conditional classes and text
// - If onSale: show "SALE" badge, red border, strikethrough original price
// - Show sale price if on sale, regular price if not
return (
<div className="product">
<h3>{product.name}</h3>
<p>{product.description}</p>
{/* Add price and badge here */}
</div>
);
}
Solution:
function ProductCard({ product }) {
return (
<div className={`product ${product.onSale ? "on-sale" : ""}`}>
<h3>{product.name}</h3>
<p>{product.description}</p>
{/* Conditional badge */}
{product.onSale && (
<span className="sale-badge">SALE</span>
)}
{/* Conditional price display */}
<div className="price">
{product.onSale ? (
<>
<span className="original-price">
${product.originalPrice}
</span>
<span className="sale-price">
${product.salePrice}
</span>
</>
) : (
<span className="regular-price">
${product.price}
</span>
)}
</div>
</div>
);
}
Exercise 3: Fix the Bug
This code has a bug. The class is not being applied correctly:
function Button({ isPrimary, isLarge }) {
return (
<button className="btn ${isPrimary ? 'btn-primary' : 'btn-secondary'}">
Click me
</button>
);
}
Bug: Using regular quotes instead of backticks for template literal.
Solution:
function Button({ isPrimary, isLarge }) {
return (
<button className={`btn ${isPrimary ? 'btn-primary' : 'btn-secondary'}`}>
Click me
</button>
);
}
π‘ Key Takeaways
| Concept | What It Means | Example |
|---|---|---|
| Conditional Text | Change content inside element | {soldOut ? "SOLD OUT" : "$12"} |
| Conditional Class | Change styling of element | className={\pizza ${soldOut ? "sold-out" : ""}\} |
| Template Literal | String with embedded JS | ` text ${variable} ` |
| Keep Element | Don't replace whole element, just content | Same <span>, different text |
| Dynamic Classes | Combine static + dynamic class names | "pizza " + (soldOut ? "sold-out" : "") |
The Pattern:
// Conditional text
<span>{condition ? "Text A" : "Text B"}</span>
// Conditional class
<div className={`static-class ${condition ? "dynamic-class" : ""}`}>
Golden Rules:
- Same element, different content = conditional text (preferred)
- Same element, different style = conditional class
- Use backticks `
`` for template literals with embedded JS - Use
${}inside template literals for JavaScript expressions - Different structure entirely = conditional element (early return or ternary)
One Sentence Summary: > "Instead of replacing the whole HTML element, keep the element and use curly braces to dynamically change its text content with ternary operators, and use backtick template literals to conditionally add CSS classes - like giving the same box different labels and paint colors!"