🔀 Conditional Rendering

Showing Different UI Based on Conditions

What is Conditional Rendering?

Conditional rendering means showing different content based on certain conditions - like showing a login button if the user is logged out, or a welcome message if they're logged in.

Real-World Examples:

  • Show loading spinner while fetching data
  • Display different UI for admin vs regular users
  • Show error messages when something goes wrong
  • Hide/show sections based on user actions

🎯 If/Else with Return

The simplest approach - use regular JavaScript if statements:

function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h1>Welcome back!</h1>;
  }
  return <h1>Please log in.</h1>;
}

// Usage
<Greeting isLoggedIn={true} />   // Shows "Welcome back!"
<Greeting isLoggedIn={false} />  // Shows "Please log in."

With Multiple Conditions:

function UserStatus({ status }) {
  if (status === 'loading') {
    return <p>Loading...</p>;
  }
  
  if (status === 'error') {
    return <p>Error occurred!</p>;
  }
  
  if (status === 'success') {
    return <p>Data loaded successfully!</p>;
  }
  
  return <p>Unknown status</p>;
}

❓ Ternary Operator (Inline)

Perfect for simple conditions inside JSX:

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

// Shorter version for simple elements
function Status({ isActive }) {
  return (
    <p>Status: {isActive ? 'Active' : 'Inactive'}</p>
  );
}

Nested Ternaries (Use Sparingly):

function Score({ score }) {
  return (
    <div>
      Grade: {
        score >= 90 ? 'A' :
        score >= 80 ? 'B' :
        score >= 70 ? 'C' :
        score >= 60 ? 'D' : 'F'
      }
    </div>
  );
}

// Better approach - use function
function Score({ score }) {
  const getGrade = () => {
    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()}</div>;
}

✅ Logical && Operator

Show something only if condition is true (no else case):

function Notifications({ count }) {
  return (
    <div>
      <h2>Inbox</h2>
      {count > 0 && (
        <span className="badge">{count} new messages</span>
      )}
    </div>
  );
}

// Multiple conditions
function UserProfile({ user, isAdmin }) {
  return (
    <div>
      <h2>{user.name}</h2>
      {user.isVerified && <span>✓ Verified</span>}
      {user.isPremium && <span>⭐ Premium</span>}
      {isAdmin && <button>Admin Panel</button>}
    </div>
  );
}

⚠️ Be Careful with Falsy Values!

// ❌ Shows "0" if count is 0
{count && <p>{count} items</p>}

// ✅ Correct - explicit check
{count > 0 && <p>{count} items</p>}

🔄 Rendering Nothing

Return null to render nothing:

function WarningBanner({ show, message }) {
  if (!show) {
    return null;  // Component renders nothing
  }
  
  return (
    <div className="warning">
      ⚠️ {message}
    </div>
  );
}

// Usage
<WarningBanner show={false} message="Error!" />  // Renders nothing
<WarningBanner show={true} message="Error!" />   // Shows warning

🎨 Conditional CSS Classes

function Button({ isPrimary, isDisabled, children }) {
  // Method 1: Template literal
  const className = `btn ${isPrimary ? 'btn-primary' : 'btn-secondary'} ${isDisabled ? 'disabled' : ''}`;
  
  return (
    <button className={className} disabled={isDisabled}>
      {children}
    </button>
  );
}

// Method 2: Array join
function Card({ isActive, isHighlighted }) {
  const classes = [
    'card',
    isActive && 'active',
    isHighlighted && 'highlighted'
  ].filter(Boolean).join(' ');
  
  return <div className={classes}>...</div>;
}

🔄 Loading States

function DataDisplay() {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  
  // Simulate data fetch
  useEffect(() => {
    setTimeout(() => {
      // Simulate success or error
      if (Math.random() > 0.3) {
        setData({ name: 'John', age: 30 });
      } else {
        setError('Failed to load data');
      }
      setIsLoading(false);
    }, 2000);
  }, []);
  
  // Loading state
  if (isLoading) {
    return (
      <div className="spinner">
        <p>Loading...</p>
      </div>
    );
  }
  
  // Error state
  if (error) {
    return (
      <div className="error">
        <p>❌ {error}</p>
        <button onClick={() => window.location.reload()}>
          Retry
        </button>
      </div>
    );
  }
  
  // Success state
  return (
    <div className="data">
      <h2>{data.name}</h2>
      <p>Age: {data.age}</p>
    </div>
  );
}

🔐 Authentication Example

function App() {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  
  // Simulate checking auth status
  useEffect(() => {
    setTimeout(() => {
      // Simulate logged in user
      setUser({ 
        name: 'Alice', 
        role: 'admin',
        avatar: 'avatar.jpg'
      });
      setIsLoading(false);
    }, 1000);
  }, []);
  
  if (isLoading) {
    return <div>Checking authentication...</div>;
  }
  
  return (
    <div>
      {user ? (
        <div>
          {/* Logged in view */}
          <header>
            <h1>Welcome, {user.name}!</h1>
            <img src={user.avatar} alt={user.name} />
            
            {/* Admin-only section */}
            {user.role === 'admin' && (
              <button>Admin Dashboard</button>
            )}
            
            <button onClick={() => setUser(null)}>Logout</button>
          </header>
          
          <main>
            <h2>Dashboard</h2>
            <p>Your content here...</p>
          </main>
        </div>
      ) : (
        <div>
          {/* Logged out view */}
          <h1>Please Log In</h1>
          <button onClick={() => setUser({ name: 'Guest', role: 'user' })}>
            Login
          </button>
        </div>
      )}
    </div>
  );
}

📋 List with Conditional Items

function TaskList() {
  const [showCompleted, setShowCompleted] = useState(true);
  const [tasks, setTasks] = useState([
    { id: 1, text: 'Learn React', completed: true },
    { id: 2, text: 'Build Project', completed: false },
    { id: 3, text: 'Deploy App', completed: true }
  ]);
  
  // Filter tasks based on showCompleted
  const filteredTasks = showCompleted 
    ? tasks 
    : tasks.filter(task => !task.completed);
  
  return (
    <div>
      <h2>My Tasks</h2>
      
      {/* Toggle button */}
      <label>
        <input 
          type="checkbox"
          checked={showCompleted}
          onChange={(e) => setShowCompleted(e.target.checked)}
        />
        Show completed tasks
      </label>
      
      {/* Empty state */}
      {filteredTasks.length === 0 ? (
        <p>No tasks to show</p>
      ) : (
        <ul>
          {filteredTasks.map(task => (
            <li 
              key={task.id}
              className={task.completed ? 'completed' : ''}
            >
              {task.text}
              {task.completed && ' ✓'}
            </li>
          ))}
        </ul>
      )}
      
      {/* Task count */}
      <p>
        {tasks.filter(t => !t.completed).length} tasks remaining
      </p>
    </div>
  );
}

🎯 Complete Example: Dashboard

function Dashboard() {
  const [user, setUser] = useState({
    name: 'John Doe',
    role: 'premium',
    notifications: 5,
    isOnline: true
  });
  
  const [view, setView] = useState('overview'); // 'overview', 'profile', 'settings'
  const [showNotifications, setShowNotifications] = useState(false);
  
  return (
    <div className="dashboard">
      {/* Header */}
      <header>
        <h1>Dashboard</h1>
        
        {/* Online status */}
        <span className={user.isOnline ? 'online' : 'offline'}>
          {user.isOnline ? '🟢 Online' : '⚪ Offline'}
        </span>
        
        {/* Notifications */}
        <div className="notifications">
          <button onClick={() => setShowNotifications(!showNotifications)}>
            🔔
            {user.notifications > 0 && (
              <span className="badge">{user.notifications}</span>
            )}
          </button>
          
          {showNotifications && (
            <div className="notification-dropdown">
              {user.notifications === 0 ? (
                <p>No new notifications</p>
              ) : (
                <p>You have {user.notifications} new notifications</p>
              )}
            </div>
          )}
        </div>
      </header>
      
      {/* Navigation */}
      <nav>
        <button 
          className={view === 'overview' ? 'active' : ''}
          onClick={() => setView('overview')}
        >
          Overview
        </button>
        <button 
          className={view === 'profile' ? 'active' : ''}
          onClick={() => setView('profile')}
        >
          Profile
        </button>
        <button 
          className={view === 'settings' ? 'active' : ''}
          onClick={() => setView('settings')}
        >
          Settings
        </button>
      </nav>
      
      {/* Main content - conditional rendering */}
      <main>
        {view === 'overview' && (
          <div>
            <h2>Overview</h2>
            
            {/* Premium badge */}
            {user.role === 'premium' && (
              <div className="premium-badge">
                ⭐ Premium Member
              </div>
            )}
            
            <p>Welcome back, {user.name}!</p>
          </div>
        )}
        
        {view === 'profile' && (
          <div>
            <h2>Profile</h2>
            <p>Name: {user.name}</p>
            <p>Role: {user.role}</p>
          </div>
        )}
        
        {view === 'settings' && (
          <div>
            <h2>Settings</h2>
            
            {user.role !== 'admin' ? (
              <p>Some settings require admin access</p>
            ) : (
              <button>Advanced Settings</button>
            )}
          </div>
        )}
      </main>
    </div>
  );
}

⚠️ Common Patterns

Empty States:

function ItemList({ items }) {
  return (
    <div>
      {items.length === 0 ? (
        <div className="empty-state">
          <p>No items found</p>
          <button>Add First Item</button>
        </div>
      ) : (
        <ul>
          {items.map(item => <li key={item.id}>{item.name}</li>)}
        </ul>
      )}
    </div>
  );
}

Feature Flags:

function App() {
  const features = {
    darkMode: true,
    betaFeatures: false,
    analytics: true
  };
  
  return (
    <div>
      {features.darkMode && <DarkModeToggle />}
      {features.betaFeatures && <BetaFeatures />}
      {features.analytics && <Analytics />}
    </div>
  );
}

🎯 Key Takeaways