Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /React
  4. /Conditional Rendering
Your Progress0%
0 of 42 completed

React Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App

Conditional Rendering

Show the right content at the right time

Not all content should be visible all the time. Sometimes you want to show a loading spinner, other times an error message, and when everything's ready, the actual data. This is called conditional rendering - displaying different UI based on certain conditions. It's one of the most important concepts in React, and in this lesson, you'll learn all the techniques to master it.

What is Conditional Rendering?

Conditional rendering means showing or hiding parts of your UI based on conditions - just like an if statement in regular programming. Instead of always rendering everything, you decide what to render based on:

  • User authentication status (logged in or not)
  • Data loading state (loading, error, or success)
  • User permissions (admin vs regular user)
  • Form validation (valid or invalid input)
  • Feature flags (new feature enabled or not)
  • Device type (mobile vs desktop)
  • Time of day (morning vs evening greetings)

In React, components can return different JSX based on conditions, making your UI dynamic and responsive to the application state.

Method 1: If/Else Statements

The most straightforward way to conditionally render is using regular if/else statements before the return statement:

Basic If/Else

basic-if-else.jsx
function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h1>Welcome back!</h1>
  }
  
  return <h1>Please sign in</h1>
}

// Usage:
<Greeting isLoggedIn={true} />  // Shows: Welcome back!
<Greeting isLoggedIn={false} /> // Shows: Please sign in

If/Else with Multiple Conditions

multiple-conditions.jsx
function UserDashboard({ user }) {
  if (!user) {
    return <div>Loading user data...</div>
  }
  
  if (user.role === 'admin') {
    return (
      <div>
        <h1>Admin Dashboard</h1>
        <AdminPanel />
      </div>
    )
  }
  
  if (user.role === 'moderator') {
    return (
      <div>
        <h1>Moderator Dashboard</h1>
        <ModeratorPanel />
      </div>
    )
  }
  
  // Default case - regular user
  return (
    <div>
      <h1>User Dashboard</h1>
      <UserPanel />
    </div>
  )
}

Early Returns

A common pattern is using "early returns" to handle edge cases first:

early-returns.jsx
function ProductList({ products, isLoading, error }) {
  // Handle loading state
  if (isLoading) {
    return <LoadingSpinner />
  }
  
  // Handle error state
  if (error) {
    return (
      <div className="error">
        <p>Error: {error.message}</p>
        <button onClick={retry}>Try Again</button>
      </div>
    )
  }
  
  // Handle empty state
  if (!products || products.length === 0) {
    return <p>No products found</p>
  }
  
  // Happy path - show the products
  return (
    <div>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  )
}

πŸ’‘ When to Use If/Else

Use if/else statements when:
β€’ You're returning completely different components
β€’ You have multiple conditions to check
β€’ The logic is complex and needs multiple lines
β€’ You want to use early returns for edge cases

Method 2: Ternary Operator

The ternary operator (condition ? true : false) is perfect for conditional rendering inside your JSX:

Basic Ternary

basic-ternary.jsx
function LoginButton({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? (
        <button>Logout</button>
      ) : (
        <button>Login</button>
      )}
    </div>
  )
}

// Inline version for simple cases
function Status({ isOnline }) {
  return <span>{isOnline ? '🟒 Online' : '⚫ Offline'}</span>
}

Ternary for Elements vs Text

ternary-elements.jsx
function MessageBox({ hasMessages, messageCount }) {
  return (
    <div>
      {/* Conditional element rendering */}
      {hasMessages ? (
        <div className="messages">
          <h3>You have {messageCount} new messages</h3>
          <MessageList />
        </div>
      ) : (
        <div className="no-messages">
          <p>No new messages</p>
        </div>
      )}
      
      {/* Conditional text */}
      <p>
        Inbox: {messageCount > 0 ? `${messageCount} unread` : 'Empty'}
      </p>
    </div>
  )
}

Nested Ternaries (Use Sparingly!)

nested-ternary.jsx
function ScoreGrade({ score }) {
  return (
    <div>
      {/* ⚠️ This works but gets hard to read */}
      Grade: {
        score >= 90 ? 'A' :
        score >= 80 ? 'B' :
        score >= 70 ? 'C' :
        score >= 60 ? 'D' : 'F'
      }
    </div>
  )
}

// βœ… Better: Use a function
function ScoreGrade({ score }) {
  const getGrade = (score) => {
    if (score >= 90) return 'A'
    if (score >= 80) return 'B'
    if (score >= 70) return 'C'
    if (score >= 60) return 'D'
    return 'F'
  }
  
  return <div>Grade: {getGrade(score)}</div>
}

Avoid Deeply Nested Ternaries

While you can nest ternary operators, it quickly becomes unreadable. If you have more than two conditions, use if/else statements or extract the logic to a function.

ReactPlayground.jsx
Code Editor
Preview

πŸ’‘ Tip: Edit the code above and click "Run" to see your changes

Method 3: Logical AND Operator (&&)

The logical AND operator (&&) is perfect when you want to render something only if a condition is true, with nothing rendered if it's false:

Basic && Operator

basic-and.jsx
function Notifications({ hasNotifications, count }) {
  return (
    <div>
      <h1>My App</h1>
      
      {/* Only show if hasNotifications is true */}
      {hasNotifications && (
        <div className="notification-badge">
          {count} new notifications
        </div>
      )}
    </div>
  )
}

// If hasNotifications is false, nothing renders
// If hasNotifications is true, the div renders

Multiple Conditions with &&

multiple-and.jsx
function UserProfile({ user, isOwner, isPremium }) {
  return (
    <div>
      <h1>{user.name}</h1>
      
      {/* Show edit button only if user is owner */}
      {isOwner && <button>Edit Profile</button>}
      
      {/* Show premium badge only if user is premium */}
      {isPremium && <span className="badge">⭐ Premium</span>}
      
      {/* Show admin panel only if both conditions true */}
      {isOwner && isPremium && (
        <div className="admin-panel">
          <h3>Premium Owner Features</h3>
        </div>
      )}
    </div>
  )
}

Common Patterns

common-and-patterns.jsx
function DataDisplay({ data, isLoading, error }) {
  return (
    <div>
      {/* Show loading spinner while loading */}
      {isLoading && <Spinner />}
      
      {/* Show error message if there's an error */}
      {error && (
        <div className="error">
          Error: {error.message}
        </div>
      )}
      
      {/* Show data only if it exists and we're not loading */}
      {!isLoading && data && (
        <div className="data">
          {data.map(item => <Item key={item.id} {...item} />)}
        </div>
      )}
      
      {/* Show empty state if no data and not loading */}
      {!isLoading && !data && (
        <p>No data available</p>
      )}
    </div>
  )
}

Watch Out for Falsy Values!

Be careful with && when the left side could be 0 or "":
{count && <div>{count} items</div>}
If count is 0, it will render "0" instead of nothing!

Use: {count > 0 && <div>{count} items</div>}
Or: {!!count && <div>{count} items</div>}

Method 4: Logical OR Operator (||)

The logical OR operator (||) is useful for providing fallback or default values:

logical-or.jsx
function UserGreeting({ username, displayName }) {
  return (
    <div>
      {/* Use displayName if it exists, otherwise use username */}
      <h1>Hello, {displayName || username}!</h1>
      
      {/* Use custom message or default */}
      <p>{user.bio || 'No bio provided'}</p>
      
      {/* Show user avatar or placeholder */}
      <img src={user.avatar || '/default-avatar.png'} alt="Avatar" />
    </div>
  )
}

πŸ’‘ Nullish Coalescing (??)

Modern JavaScript has the nullish coalescing operator (??) which only falls back for null or undefined, not for other falsy values like 0 or "":
count || 'N/A' β†’ "N/A" even if count is 0
count ?? 'N/A' β†’ 0 if count is 0

Method 5: Returning Null

Sometimes you want a component to render nothing at all. Return null to render nothing:

return-null.jsx
function AdminPanel({ user }) {
  // Don't render anything if user is not admin
  if (!user.isAdmin) {
    return null
  }
  
  return (
    <div className="admin-panel">
      <h2>Admin Controls</h2>
      <AdminButtons />
    </div>
  )
}

// Example with multiple conditions
function SpecialOffer({ isPremium, hasSeenOffer, offerExpired }) {
  // Don't show if any of these conditions are true
  if (isPremium || hasSeenOffer || offerExpired) {
    return null
  }
  
  return (
    <div className="special-offer">
      <h3>Limited Time Offer!</h3>
      <button>Upgrade Now</button>
    </div>
  )
}

Method 6: Element Variables

You can store JSX elements in variables and conditionally assign them:

element-variables.jsx
function StatusMessage({ status }) {
  let message
  let icon
  
  if (status === 'success') {
    icon = 'βœ…'
    message = <p className="success">Operation successful!</p>
  } else if (status === 'error') {
    icon = '❌'
    message = <p className="error">Something went wrong</p>
  } else if (status === 'warning') {
    icon = '⚠️'
    message = <p className="warning">Please review your input</p>
  } else {
    icon = 'ℹ️'
    message = <p className="info">Processing...</p>
  }
  
  return (
    <div className="status-box">
      <span className="icon">{icon}</span>
      {message}
    </div>
  )
}

This approach is great when:

  • You have complex conditional logic
  • You want to reuse the same element variable
  • You need to build up the element conditionally

Method 7: Switch Statements

For multiple distinct conditions, switch statements can be cleaner than if/else chains:

switch-statement.jsx
function StatusIcon({ status }) {
  switch (status) {
    case 'loading':
      return <Spinner />
    
    case 'success':
      return <CheckIcon />
    
    case 'error':
      return <ErrorIcon />
    
    case 'warning':
      return <WarningIcon />
    
    default:
      return <InfoIcon />
  }
}

// Or using a switch with element variable
function Dashboard({ userRole }) {
  let content
  
  switch (userRole) {
    case 'admin':
      content = <AdminDashboard />
      break
    
    case 'moderator':
      content = <ModeratorDashboard />
      break
    
    case 'user':
      content = <UserDashboard />
      break
    
    default:
      content = <GuestDashboard />
  }
  
  return (
    <div className="dashboard">
      {content}
    </div>
  )
}

Method 8: Object Mapping

A clever technique is to use objects to map conditions to components:

object-mapping.jsx
function PaymentStatus({ status }) {
  const statusComponents = {
    pending: <PendingIcon />,
    processing: <ProcessingSpinner />,
    completed: <SuccessIcon />,
    failed: <ErrorIcon />,
    refunded: <RefundIcon />
  }
  
  // Return the component based on status, or null if not found
  return statusComponents[status] || null
}

// More complex example with full components
function UserDashboard({ role }) {
  const dashboards = {
    admin: <AdminDashboard />,
    moderator: <ModeratorDashboard />,
    premium: <PremiumDashboard />,
    user: <UserDashboard />,
    guest: <GuestDashboard />
  }
  
  return dashboards[role] || dashboards.guest
}

// With functions for dynamic content
function Notification({ type, message }) {
  const notificationConfig = {
    success: {
      icon: 'βœ…',
      className: 'bg-green-100 text-green-800'
    },
    error: {
      icon: '❌',
      className: 'bg-red-100 text-red-800'
    },
    warning: {
      icon: '⚠️',
      className: 'bg-yellow-100 text-yellow-800'
    },
    info: {
      icon: 'ℹ️',
      className: 'bg-blue-100 text-blue-800'
    }
  }
  
  const config = notificationConfig[type] || notificationConfig.info
  
  return (
    <div className={`notification ${config.className}`}>
      <span>{config.icon}</span>
      <p>{message}</p>
    </div>
  )
}

πŸ’‘ When to Use Object Mapping

Object mapping is great when:
β€’ You have many simple conditions (5+)
β€’ Each condition maps to a component or configuration
β€’ You want clean, readable code
β€’ Conditions are based on string/number values

ReactPlayground.jsx
Code Editor
Preview

πŸ’‘ Tip: Edit the code above and click "Run" to see your changes

Best Practices for Conditional Rendering

Follow these guidelines to write clean conditional rendering:

1. Choose the Right Method

  • If/Else: Multiple conditions, different components, early returns
  • Ternary (? :): Two options, inline rendering, simple conditions
  • Logical AND (&&): Show something or nothing, single condition
  • Logical OR (||): Fallback values, default content
  • Switch/Object: Many distinct options based on one value

2. Keep It Simple

keep-simple.jsx
// ❌ Too complex
{isLoggedIn && user.isPremium && !user.isBanned && hasAccess && 
 (userRole === 'admin' || userRole === 'moderator') && (
  <ComplexComponent />
)}

// βœ… Extract to variable
const canAccessFeature = isLoggedIn && 
                         user.isPremium && 
                         !user.isBanned && 
                         hasAccess &&
                         (userRole === 'admin' || userRole === 'moderator')

{canAccessFeature && <ComplexComponent />}

// βœ… Or extract to function
const canUserAccess = (user) => {
  if (!user.isLoggedIn || user.isBanned) return false
  if (!user.isPremium || !user.hasAccess) return false
  return user.role === 'admin' || user.role === 'moderator'
}

{canUserAccess(user) && <ComplexComponent />}

3. Handle All Cases

handle-all-cases.jsx
// ❌ Forgot the loading state
function UserProfile({ user, error }) {
  if (error) return <Error />
  return <Profile user={user} />
}

// βœ… Handle all possible states
function UserProfile({ user, isLoading, error }) {
  if (isLoading) return <Spinner />
  if (error) return <Error error={error} />
  if (!user) return <NotFound />
  return <Profile user={user} />
}

4. Avoid Negative Conditions When Possible

avoid-negative.jsx
// ❌ Hard to read
{!isNotLoggedIn && !hasNoAccess && <Content />}

// βœ… Use positive conditions
{isLoggedIn && hasAccess && <Content />}

5. Use Early Returns for Guards

early-returns-guards.jsx
// βœ… Clean and readable
function ProtectedContent({ user, data }) {
  // Guard clauses at the top
  if (!user) return <Login />
  if (!user.hasAccess) return <Forbidden />
  if (!data) return <Loading />
  
  // Happy path
  return (
    <div>
      <h1>Welcome, {user.name}!</h1>
      <DataDisplay data={data} />
    </div>
  )
}

Common Conditional Rendering Patterns

Loading, Error, Success Pattern

loading-error-success.jsx
function DataFetcher({ url }) {
  const [data, setData] = React.useState(null)
  const [isLoading, setIsLoading] = React.useState(true)
  const [error, setError] = React.useState(null)
  
  // ... fetch logic ...
  
  if (isLoading) {
    return (
      <div className="loading">
        <Spinner />
        <p>Loading data...</p>
      </div>
    )
  }
  
  if (error) {
    return (
      <div className="error">
        <h2>Oops! Something went wrong</h2>
        <p>{error.message}</p>
        <button onClick={retry}>Try Again</button>
      </div>
    )
  }
  
  return (
    <div className="success">
      <DataDisplay data={data} />
    </div>
  )
}

Empty State Pattern

empty-state.jsx
function ItemList({ items, isLoading }) {
  if (isLoading) {
    return <LoadingSkeleton />
  }
  
  if (!items || items.length === 0) {
    return (
      <div className="empty-state">
        <EmptyIcon />
        <h3>No items yet</h3>
        <p>Get started by adding your first item</p>
        <button>Add Item</button>
      </div>
    )
  }
  
  return (
    <ul>
      {items.map(item => (
        <ListItem key={item.id} item={item} />
      ))}
    </ul>
  )
}

Permission-Based Rendering

permission-based.jsx
function FeatureAccess({ user, requiredRole }) {
  const hasPermission = user.roles.includes(requiredRole)
  
  if (!hasPermission) {
    return (
      <div className="no-access">
        <LockIcon />
        <p>You don't have permission to access this feature</p>
        <a href="/upgrade">Upgrade your account</a>
      </div>
    )
  }
  
  return <Feature />
}

// Usage:
<FeatureAccess user={currentUser} requiredRole="premium">
  <PremiumFeature />
</FeatureAccess>

Key Takeaways

  • Conditional rendering shows/hides UI based on conditions
  • Use if/else before return for multiple conditions or early returns
  • Use ternary operator (? :) for inline conditions with two options
  • Use logical AND (&&) to show something or nothing
  • Watch out for falsy values like 0 with &&
  • Return null to render nothing
  • Use switch statements or object mapping for many options
  • Extract complex conditions to variables or functions
  • Handle all states: loading, error, empty, success
  • Use early returns for guard clauses
  • Avoid deeply nested ternaries - they're hard to read

What's Next?

You now know how to show the right content at the right time using conditional rendering. But what about rendering multiple items from an array? What if you have a list of users, products, or messages to display?

That's where lists and keys come in! In the next lesson, you'll learn how to render arrays of data, why the key prop is crucial, and how to create dynamic lists that React can efficiently update. Get ready to bring your data to life! πŸš€

Learning how to show/hide content dynamically in React!

Previous
JSX Expressions and Variables
Next
Lists and Keys

Never Miss a New React Tutorial

Join 2,000+ developers learning React step-by-step. Get new tutorials, tips, and exclusive resources delivered to your inbox - completely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

React Tutorials

0 of 42 completed

Your Progress0%

Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

Β© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo