# Conditional Rendering in React Apps

In simple term, it is used to render or show UI elements / Components based on condition.

Conditional rendering in React is **the process of displaying different UI elements or components based on specific conditions, such as the application's state, user roles, or input data**. It uses standard JavaScript logic and syntax to dynamically control what is rendered to the user.

There are many ways to implement conditional rendering, each one has specific use case. Developers can use several JavaScript techniques to implement conditional rendering in React components: 

| **Technique** | **Description** | **Use Case** |
| --- | --- | --- |
| `if` **statements** | Use standard `if` or `if-else` blocks **outside** of the `return` statement in a functional component to decide which JSX to return. This is ideal for early returns or complex logic. | Displaying a login form or a user dashboard depending on an `isLoggedIn` state. |
| **Ternary Operator (**`? :`) | A concise inline `if-else` statement within JSX. It is used when you need to render one of two possible outcomes. | Toggling button text between "Login" and "Logout" based on a boolean `isLoggedIn` variable. |
| **Logical** `&&` Operator | Renders the element on the right side if the condition on the left side is `true`; otherwise, it renders nothing (`null`). This is known as short-circuit evaluation. | Showing a notification message only if there are unread messages (`messageCount > 0 && <Notification />`). |
| **Element Variables** | Assign JSX to a variable within the component logic and then include the variable in the main `return` statement. | A cleaner way to handle slightly more complex conditional logic while keeping the `return` block simple. |
| `switch` **statements** | Useful for handling multiple possible conditions in a readable manner. Like `if-else` statements, they are typically used outside the main `return` to define a variable holding the output. | Rendering different components based on a `userRole` (e.g., 'viewer', 'editor', 'admin'). |

## Detailed Example of each **Technique** 

These examples are based on production-grade standards.

### 1\. **Logical AND (&&) Operator**

**Use case:** Show optional UI elements that depend on a single condition

```javascript
function NotificationBadge({ unreadCount }) {
  return (
    <div className="nav-item">
      <BellIcon />
      {unreadCount > 0 && (
        <span className="badge">{unreadCount}</span>
      )}
    </div>
  );
}
```

**Why this pattern:** Perfect when you want to render something *or nothing*. If `unreadCount` is 0, the badge doesn't appear at all.

**Production tip:** <mark>Be careful with falsy values.</mark> `{count && <Badge />}` will render "0" on screen if count is 0. Use `{count > 0 && <Badge />}` instead. And you don’t want to show that.

---

### 2\. **Ternary Operator (? :)**

**Use case:** Toggle between two different UI states

```javascript
function SubscribeButton({ isSubscribed, onToggle }) {
  return (
    <button 
      onClick={onToggle}
      className={isSubscribed ? "btn-secondary" : "btn-primary"}
    >
      {isSubscribed ? "Unsubscribe" : "Subscribe"}
    </button>
  );
}
```

**Why this pattern:** When you need to show *one thing or another* (not nothing). Both states always render something.

**Production tip:** Keep ternaries simple. If the JSX gets complex, extract to variables or use early returns instead.

---

## 3\. **Early Return**

**Use case:** Handle loading/error states before rendering main content. When you want to show skeleton loader while fetching and processing data.

```javascript
function UserProfile({ userId }) {
  const { data, isLoading, error } = useUser(userId);

  if (isLoading) {
    return <Spinner />;
  }

  if (error) {
    return <ErrorMessage error={error} />;
  }

  if (!data) {
    return <EmptyState message="User not found" />;
  }

  // Main rendering logic - clean and focused
  return (
    <div className="profile">
      <Avatar src={data.avatar} />
      <h1>{data.name}</h1>
      <Bio text={data.bio} />
    </div>
  );
}
```

**Why this pattern:** Keeps your main component logic clean by handling edge cases first. No deeply nested ternaries or complex conditionals.

**Production tip:** This is the most maintainable pattern for components with multiple states (loading, error, empty, success). Always handle edge cases at the top.

---

### 4\. `if` Statements

**Use case:** There is multiple conditions with default state. Show components based on conditions. For example same component has different version. Render it based on version.

```javascript
function Dashboard({ user, permissions }) {
  let content;

  if (!user) {
    content = <LoginPrompt />;
  } else if (!user.emailVerified) {
    content = <EmailVerificationRequired email={user.email} />;
  } else if (user.subscription === 'expired') {
    content = <SubscriptionExpiredNotice />;
  } else {
    content = <DashboardContent user={user} permissions={permissions} />;
  }

  return (
    <div className="dashboard-container">
      <Header user={user} />
      {content}
    </div>
  );
}
```

**Why this pattern:** When you have multiple `else-if` conditions, it's cleaner to handle them before the return statement rather than nesting ternaries.

**Production tip:** Use this when logic is too complex for ternaries but doesn't require early returns.

---

### 5\. **Element Variables**

**Use case:** Building dynamic UI elements based on data state. Define elements using JavaScript variables.

```javascript
function OrderStatus({ order }) {
  // Define UI elements based on order status
  let statusBadge;
  let actionButton;

  if (order.status === 'pending') {
    statusBadge = <Badge color="yellow">Pending Payment</Badge>;
    actionButton = <button>Complete Payment</button>;
  } else if (order.status === 'processing') {
    statusBadge = <Badge color="blue">Processing</Badge>;
    actionButton = <button disabled>Preparing Order...</button>;
  } else if (order.status === 'shipped') {
    statusBadge = <Badge color="green">Shipped</Badge>;
    actionButton = <button>Track Package</button>;
  } else {
    statusBadge = <Badge color="gray">Delivered</Badge>;
    actionButton = <button>Leave Review</button>;
  }

  return (
    <div className="order-card">
      <h3>Order #{order.id}</h3>
      {statusBadge}
      <div className="order-items">
        {order.items.map(item => <OrderItem key={item.id} {...item} />)}
      </div>
      <div className="order-total">${order.total}</div>
      {actionButton}
    </div>
  );
} 
```

**Why this pattern:** Keeps your return statement clean and readable while handling conditional logic for multiple related elements.

**Production tip:** Great for when multiple parts of your UI change together based on the same condition.

---

### 6\. `switch` Statements

**Use case:** Role-based access control and rendering different admin panels

```javascript
function AdminPanel({ userRole, userData }) {
  let panelContent;

  switch (userRole) {
    case 'viewer':
      panelContent = (
        <div className="viewer-panel">
          <h2>Viewer Dashboard</h2>
          <ReportsList reports={userData.reports} readOnly />
          <p className="permission-note">
            You have read-only access. Contact admin for more permissions.
          </p>
        </div>
      );
      break;

    case 'editor':
      panelContent = (
        <div className="editor-panel">
          <h2>Editor Dashboard</h2>
          <ReportsList reports={userData.reports} />
          <CreateReportButton />
          <EditHistoryLog entries={userData.editHistory} />
        </div>
      );
      break;

    case 'admin':
      panelContent = (
        <div className="admin-panel">
          <h2>Admin Dashboard</h2>
          <UserManagement users={userData.allUsers} />
          <ReportsList reports={userData.allReports} />
          <SystemSettings />
          <AuditLogs />
        </div>
      );
      break;

    case 'superadmin':
      panelContent = (
        <div className="superadmin-panel">
          <h2>Super Admin Dashboard</h2>
          <OrganizationManagement />
          <BillingOverview />
          <SystemHealthMonitor />
          <DatabaseBackups />
        </div>
      );
      break;

    default:
      panelContent = (
        <div className="no-access">
          <h2>Access Denied</h2>
          <p>Your account role is not recognized. Please contact support.</p>
        </div>
      );
  }

  return (
    <div className="admin-container">
      <Sidebar role={userRole} />
      <main>{panelContent}</main>
    </div>
  );
}
```

**Why this pattern:** More readable than multiple `if-else` statements when you have 4+ distinct conditions based on a single value.

**Production tip:** Always include a `default` case for unexpected values. This prevents rendering nothing or breaking when data is malformed.

---

### Quick summery - When to Use Each Conditional Rendering Pattern

| Pattern | Best For | Example Use Cases |
| --- | --- | --- |
| `&&` | Optional elements | Badges, tooltips, conditional features, notification indicators |
| **Ternary (**`? :`) | Binary choices | Button text, icon toggles, class names, toggle states |
| **Early Return** | Multiple states | Data fetching, authentication checks, validation, loading/error states |
| `if` statements | 2-4 conditions with `else-if` | Complex logic before return, multi-step authentication flows |
| **Element Variables** | Multiple related elements changing together | Keeping return statement clean, building complex conditional UIs |
| `switch` | 4+ distinct cases from single value | Role-based rendering, status types, notification types, theme selection |

Using this your code will be clean and easy to debug. Use this as per requirement. Merge conditions to avoid complexity.
