Sitemap
mirbasit01

mirbasit01

Front-End Developer | React.js | Next.js | TypeScript | Tailwind CSS | Web3.js | Smart Contracts | Creating responsive & innovative web apps

Conditional Rendering in React.js

7 min readOct 3, 2025

--

Press enter or click to view image in full size

Introduction

Conditional rendering is one of the most fundamental concepts in React development. It allows you to display different UI elements based on certain conditions, making your applications dynamic and interactive. Whether you’re showing a loading spinner, displaying user-specific content, or handling error states, conditional rendering is your go-to technique.

Get mirbasit01’s stories in your inbox

Join Medium for free to get updates from this writer.

In this comprehensive guide, we’ll explore every method of conditional rendering in React, from basic to advanced techniques, with real-world examples you can use immediately.

What is Conditional Rendering?

Conditional rendering in React works the same way conditions work in JavaScript. You use JavaScript operators like if, else, ternary operators, and logical operators to create elements representing the current state, and React updates the UI to match them.

Method 1: If-Else Statements

The most straightforward approach using traditional JavaScript if-else logic.

Basic Example

function UserGreeting({ isLoggedIn, username }) {
if (isLoggedIn) {
return (
<div>
<h1>Welcome back, {username}!</h1>
<button>Logout</button>
</div>
);
} else {
return (
<div>
<h1>Please sign in</h1>
<button>Login</button>
</div>
);
}
}

Multiple Conditions

function Dashboard({ userRole }) {
if (userRole === 'admin') {
return (
<div>
<h1>Admin Dashboard</h1>
<button>Manage Users</button>
<button>View Analytics</button>
<button>Settings</button>
</div>
);
} else if (userRole === 'moderator') {
return (
<div>
<h1>Moderator Dashboard</h1>
<button>Review Content</button>
<button>Manage Reports</button>
</div>
);
} else if (userRole === 'user') {
return (
<div>
<h1>User Dashboard</h1>
<button>View Profile</button>
<button>My Posts</button>
</div>
);
} else {
return (
<div>
<h1>Access Denied</h1>
<p>Please contact administrator</p>
</div>
);
}
}

Method 2: Ternary Operator

Perfect for simple if-else conditions. More concise and readable for straightforward cases.

Basic Ternary

function LoginButton({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>Logout</button>
) : (
<button>Login</button>
)}
</div>
);
}

Inline Text Rendering

function CartBadge({ itemCount }) {
return (
<div className="cart-icon">
🛒
<span className="badge">
{itemCount > 0 ? itemCount : 'Empty'}
</span>
</div>
);
}

Nested Ternary (Use Carefully!)

function StatusIndicator({ status }) {
return (
<div>
{status === 'loading' ? (
<span>⏳ Loading...</span>
) : status === 'success' ? (
<span>✅ Success!</span>
) : status === 'error' ? (
<span>❌ Error occurred</span>
) : (
<span>⚪ Idle</span>
)}
</div>
);
}

Method 3: Logical && Operator

Best for rendering something or nothing. If the condition is true, render the element; otherwise, render nothing.

Basic Usage

function Notification({ hasNewMessages, messageCount }) {
return (
<div>
<h2>Inbox</h2>
{hasNewMessages && (
<div className="notification">
You have {messageCount} new messages!
</div>
)}
</div>
);
}

Multiple Conditions

function ProfilePage({ user, isOwner, isPremium }) {
return (
<div className="profile">
<h1>{user.name}</h1>
<img src={user.avatar} alt={user.name} />

{isOwner && (
<button>Edit Profile</button>
)}

{isPremium && (
<div className="premium-badge">
⭐ Premium Member
</div>
)}

{user.bio && (
<p className="bio">{user.bio}</p>
)}
</div>
);
}

Common Pitfall Warning

// ❌ WRONG - Will render "0" if count is 0
function CartItems({ count }) {
return (
<div>
{count && <p>You have {count} items</p>}
</div>
);
}
// ✅ CORRECT - Use explicit comparison
function CartItems({ count }) {
return (
<div>
{count > 0 && <p>You have {count} items</p>}
</div>
);
}

Method 4: Logical OR (||) Operator

Display a fallback when the value is falsy.

function UserProfile({ user }) {
return (
<div className="profile">
<h2>{user.name || 'Anonymous User'}</h2>
<p>{user.bio || 'No bio available'}</p>
<img src={user.avatar || '/default-avatar.png'} alt="Avatar" />
<p>Member since: {user.joinDate || 'Unknown'}</p>
</div>
);
}

Method 5: Switch Statement

Excellent for handling multiple specific conditions.

function OrderStatus({ status }) {
const renderStatus = () => {
switch(status) {
case 'pending':
return (
<div className="status pending">
<span>⏳</span>
<p>Order is being processed</p>
</div>
);
case 'confirmed':
return (
<div className="status confirmed">
<span>✓</span>
<p>Order confirmed</p>
</div>
);
case 'shipped':
return (
<div className="status shipped">
<span>🚚</span>
<p>Order shipped</p>
</div>
);
case 'delivered':
return (
<div className="status delivered">
<span>📦</span>
<p>Order delivered</p>
</div>
);
case 'cancelled':
return (
<div className="status cancelled">
<span>❌</span>
<p>Order cancelled</p>
</div>
);
default:
return (
<div className="status unknown">
<p>Status unknown</p>
</div>
);
}
};
  return (
<div className="order-status">
{renderStatus()}
</div>
);
}

Method 6: Object Mapping

Clean approach for multiple conditions without switch statements.

function PaymentMethod({ method }) {
const paymentIcons = {
credit: '💳',
debit: '💳',
paypal: '🅿️',
crypto: '₿',
cash: '💵'
};
  const paymentLabels = {
credit: 'Credit Card',
debit: 'Debit Card',
paypal: 'PayPal',
crypto: 'Cryptocurrency',
cash: 'Cash on Delivery'
};
return (
<div className="payment-method">
<span>{paymentIcons[method] || '💰'}</span>
<p>{paymentLabels[method] || 'Other Payment Method'}</p>
</div>
);
}

Component Mapping

function ContentRenderer({ type, data }) {
const componentMap = {
text: <TextContent data={data} />,
image: <ImageContent data={data} />,
video: <VideoContent data={data} />,
gallery: <GalleryContent data={data} />,
quote: <QuoteContent data={data} />
};
  return (
<div className="content-block">
{componentMap[type] || <p>Unsupported content type</p>}
</div>
);
}

Method 7: Immediately Invoked Function Expression (IIFE)

Useful for complex logic inside JSX.

function ProductCard({ product, user }) {
return (
<div className="product-card">
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p>${product.price}</p>

{(() => {
if (!user) {
return <button>Login to Purchase</button>;
}

if (product.stock === 0) {
return <button disabled>Out of Stock</button>;
}

if (user.isPremium) {
return (
<div>
<p className="discount">10% Premium Discount!</p>
<button>Buy Now - ${product.price * 0.9}</button>
</div>
);
}

return <button>Add to Cart</button>;
})()}
</div>
);
}

Real-World Examples

Example 1: Loading States

function UserData({ userId }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
  useEffect(() => {
fetchUser(userId)
.then(response => {
setData(response);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, [userId]);
if (loading) {
return (
<div className="loading">
<div className="spinner"></div>
<p>Loading user data...</p>
</div>
);
}
if (error) {
return (
<div className="error">
<h2>Error!</h2>
<p>{error}</p>
<button onClick={() => window.location.reload()}>
Try Again
</button>
</div>
);
}
if (!data) {
return (
<div className="empty">
<p>No user data found</p>
</div>
);
}
return (
<div className="user-data">
<h2>{data.name}</h2>
<p>{data.email}</p>
<p>{data.bio}</p>
</div>
);
}

Example 2: Authentication-Based Rendering

function ProtectedRoute({ user, children }) {
if (!user) {
return (
<div className="access-denied">
<h1>Access Denied</h1>
<p>Please log in to view this page</p>
<button onClick={() => navigate('/login')}>
Go to Login
</button>
</div>
);
}
  if (!user.emailVerified) {
return (
<div className="verify-email">
<h1>Email Verification Required</h1>
<p>Please verify your email to continue</p>
<button onClick={sendVerificationEmail}>
Resend Verification Email
</button>
</div>
);
}
if (user.subscription === 'expired') {
return (
<div className="subscription-expired">
<h1>Subscription Expired</h1>
<p>Renew your subscription to access premium content</p>
<button onClick={() => navigate('/pricing')}>
View Plans
</button>
</div>
);
}
return children;
}

Example 3: Form Validation Messages

function PasswordInput() {
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [touched, setTouched] = useState(false);
  const isValidLength = password.length >= 8;
const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password);
const hasNumber = /[0-9]/.test(password);
const passwordsMatch = password === confirmPassword;
return (
<div className="password-form">
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
onBlur={() => setTouched(true)}
placeholder="Enter password"
/>

{touched && (
<div className="validation-messages">
<p className={isValidLength ? 'valid' : 'invalid'}>
{isValidLength ? '✓' : '✗'} At least 8 characters
</p>
<p className={hasUpperCase ? 'valid' : 'invalid'}>
{hasUpperCase ? '✓' : '✗'} One uppercase letter
</p>
<p className={hasLowerCase ? 'valid' : 'invalid'}>
{hasLowerCase ? '✓' : '✗'} One lowercase letter
</p>
<p className={hasNumber ? 'valid' : 'invalid'}>
{hasNumber ? '✓' : '✗'} One number
</p>
</div>
)}
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
placeholder="Confirm password"
/>
{confirmPassword && !passwordsMatch && (
<p className="error">Passwords do not match</p>
)}
{confirmPassword && passwordsMatch && (
<p className="success">✓ Passwords match</p>
)}
</div>
);
}

Example 4: Dynamic Navigation Menu

function NavigationMenu({ user, currentPage }) {
return (
<nav>
<ul>
<li className={currentPage === 'home' ? 'active' : ''}>
<a href="/">Home</a>
</li>
        {user && (
<>
<li className={currentPage === 'dashboard' ? 'active' : ''}>
<a href="/dashboard">Dashboard</a>
</li>
<li className={currentPage === 'profile' ? 'active' : ''}>
<a href="/profile">Profile</a>
</li>
</>
)}
{user?.role === 'admin' && (
<li className={currentPage === 'admin' ? 'active' : ''}>
<a href="/admin">Admin Panel</a>
</li>
)}
{user?.isPremium && (
<li className={currentPage === 'premium' ? 'active' : ''}>
<a href="/premium">
<span className="premium-icon">⭐</span> Premium
</a>
</li>
)}
<li>
{user ? (
<button onClick={handleLogout}>Logout</button>
) : (
<button onClick={handleLogin}>Login</button>
)}
</li>
</ul>
</nav>
);
}

Best Practices

1. Keep It Simple

// ❌ Too complex
{user && user.isActive && user.subscription && user.subscription.status === 'active' && <PremiumContent />}
// ✅ Extract to variable
const canAccessPremium = user?.isActive && user?.subscription?.status === 'active';
{canAccessPremium && <PremiumContent />}

2. Use Early Returns

// ❌ Nested conditions
function Component({ data }) {
return (
<div>
{data ? (
data.length > 0 ? (
<List items={data} />
) : (
<p>No items</p>
)
) : (
<p>Loading...</p>
)}
</div>
);
}
// ✅ Early returns
function Component({ data }) {
if (!data) return <p>Loading...</p>;
if (data.length === 0) return <p>No items</p>;
return <List items={data} />;
}

3. Extract Complex Logic

// ❌ Logic in JSX
function ProductCard({ product, user }) {
return (
<div>
{user && product.stock > 0 && !product.isDiscontinued &&
(user.isPremium || product.price < 100) &&
<button>Buy Now</button>}
</div>
);
}
// ✅ Extract to function
function ProductCard({ product, user }) {
const canPurchase = () => {
if (!user || product.stock === 0 || product.isDiscontinued) {
return false;
}
return user.isPremium || product.price < 100;
};
return (
<div>
{canPurchase() && <button>Buy Now</button>}
</div>
);
}

4. Avoid Truthy/Falsy Pitfalls

// ❌ Can render "0"
{count && <p>{count} items</p>}
// ✅ Explicit check
{count > 0 && <p>{count} items</p>}
// ❌ Empty string renders nothing, which might be confusing
{text && <p>{text}</p>}
// ✅ Be explicit
{text !== '' && <p>{text}</p>}

Performance Considerations

Memoization for Expensive Conditions

function ExpensiveComponent({ data, filters }) {
const filteredData = useMemo(() => {
return data.filter(item => {
// Expensive filtering logic
return filters.every(filter => filter(item));
});
}, [data, filters]);
  if (filteredData.length === 0) {
return <p>No results found</p>;
}
return <List items={filteredData} />;
}

Conclusion

Conditional rendering is a cornerstone of React development. By mastering these techniques, you can create dynamic, responsive UIs that adapt to different states and user interactions. Remember:

  • Use if-else for complex, multi-branch logic
  • Use ternary operators for simple true/false conditions
  • Use && operator when rendering something or nothing
  • Use switch statements or object mapping for multiple specific conditions
  • Always consider readability and maintainability
  • Extract complex logic into separate functions
  • Be careful with truthy/falsy values

Start with simple techniques and gradually incorporate more advanced patterns as your applications grow in complexity.

What’s your favorite conditional rendering technique? Share your experiences in the comments!

#React #JavaScript #ConditionalRendering #WebDevelopment #Frontend #ReactJS #Programming

--

--

Written by mirbasit01

Front-End Developer | React.js | Next.js | TypeScript | Tailwind CSS | Web3.js | Smart Contracts | Creating responsive & innovative web apps