Skip to content

React Conditional Rendering

Overview

Conditional rendering is one of the most commonly used features in React, allowing us to display different content based on different conditions. This chapter will deeply learn various conditional judgment methods, best practices, and performance optimization techniques.

🔀 Basic Conditional Judgment

if Statement

jsx
function ConditionalWithIf() {
  const [user, setUser] = React.useState(null);
  const [loading, setLoading] = React.useState(false);

  const login = () => {
    setLoading(true);
    setTimeout(() => {
      setUser({ name: 'John', role: 'admin' });
      setLoading(false);
    }, 1000);
  };

  const logout = () => {
    setUser(null);
  };

  // Use if statement for conditional judgment
  if (loading) {
    return (
      <div style={{ textAlign: 'center', padding: '50px' }}>
        <div>⏳ Logging in...</div>
      </div>
    );
  }

  if (user) {
    return (
      <div>
        <h2>Welcome, {user.name}!</h2>
        <p>Your role: {user.role}</p>
        <button onClick={logout}>Logout</button>
      </div>
    );
  }

  return (
    <div>
      <h2>Please login</h2>
      <button onClick={login}>Login</button>
    </div>
  );
}

Ternary Operator

jsx
function ConditionalWithTernary() {
  const [theme, setTheme] = React.useState('light');
  const [notifications, setNotifications] = React.useState([]);
  const [showSettings, setShowSettings] = React.useState(false);

  const addNotification = () => {
    const newNotification = {
      id: Date.now(),
      message: `Notification ${notifications.length + 1}`,
      type: Math.random() > 0.5 ? 'info' : 'warning'
    };
    setNotifications([...notifications, newNotification]);
  };

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  const themeStyles = {
    light: { backgroundColor: '#fff', color: '#000' },
    dark: { backgroundColor: '#333', color: '#fff' }
  };

  return (
    <div style={{ ...themeStyles[theme], padding: '20px', minHeight: '400px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <h2>Conditional Rendering Demo</h2>

        {/* Simple ternary operator */}
        <button onClick={toggleTheme}>
          {theme === 'light' ? '🌙 Dark Mode' : '☀️ Light Mode'}
        </button>
      </div>

      <div style={{ marginBottom: '20px' }}>
        <button onClick={addNotification} style={{ marginRight: '10px' }}>
          Add Notification
        </button>
        <button onClick={() => setShowSettings(!showSettings)}>
          {showSettings ? 'Hide Settings' : 'Show Settings'}
        </button>
      </div>

      {/* Nested ternary operator */}
      <div>
        {notifications.length === 0 ? (
          <p>No notifications</p>
        ) : notifications.length === 1 ? (
          <p>You have 1 new notification</p>
        ) : (
          <p>You have {notifications.length} new notifications</p>
        )}
      </div>

      {/* Conditionally show settings panel */}
      {showSettings ? (
        <div style={{
          border: '1px solid #ddd',
          padding: '15px',
          marginTop: '20px',
          borderRadius: '5px'
        }}>
          <h3>Settings Panel</h3>
          <label>
            <input
              type="checkbox"
              checked={theme === 'dark'}
              onChange={toggleTheme}
            />
            Dark Mode
          </label>
        </div>
      ) : null}

      {/* Notification list */}
      <div style={{ marginTop: '20px' }}>
        {notifications.map(notification => (
          <div
            key={notification.id}
            style={{
              padding: '10px',
              margin: '5px 0',
              backgroundColor: notification.type === 'warning' ? '#fff3cd' : '#d1ecf1',
              color: notification.type === 'warning' ? '#856404' : '#0c5460',
              borderRadius: '4px'
            }}
          >
            {notification.type === 'warning' ? '⚠️' : 'ℹ️'} {notification.message}
          </div>
        ))}
      </div>
    </div>
  );
}

Logical AND Operator

jsx
function ConditionalWithLogicalAnd() {
  const [user, setUser] = React.useState({
    name: 'John',
    isVip: true,
    credits: 150,
    hasNotifications: true,
    unreadCount: 5
  });

  const [showModal, setShowModal] = React.useState(false);
  const [errors, setErrors] = React.useState([]);

  const addError = () => {
    setErrors([...errors, `Error ${errors.length + 1}: This is a sample error`]);
  };

  const clearErrors = () => {
    setErrors([]);
  };

  return (
    <div style={{ padding: '20px' }}>
      <h2>Logical AND Operator Demo</h2>

      {/* Basic conditional display */}
      {user && (
        <div style={{ marginBottom: '20px' }}>
          <h3>User Info</h3>
          <p>Name: {user.name}</p>

          {/* VIP badge */}
          {user.isVip && (
            <span style={{
              backgroundColor: '#ffd700',
              color: '#000',
              padding: '2px 8px',
              borderRadius: '10px',
              fontSize: '12px'
            }}>
              👑 VIP
            </span>
          )}

          {/* Credits display */}
          {user.credits > 100 && (
            <div style={{ color: 'green', marginTop: '10px' }}>
              🎉 Congratulations! Your credits exceed 100 points!
            </div>
          )}

          {/* Notification reminder */}
          {user.hasNotifications && user.unreadCount > 0 && (
            <div style={{
              backgroundColor: '#ff4757',
              color: 'white',
              padding: '10px',
              borderRadius: '5px',
              marginTop: '10px'
            }}>
              📬 You have {user.unreadCount} unread notifications
            </div>
          )}
        </div>
      )}

      {/* Error display */}
      {errors.length > 0 && (
        <div style={{ marginBottom: '20px' }}>
          <h3>Error List</h3>
          {errors.map((error, index) => (
            <div key={index} style={{
              backgroundColor: '#f8d7da',
              color: '#721c24',
              padding: '10px',
              margin: '5px 0',
              borderRadius: '4px',
              border: '1px solid #f5c6cb'
            }}>
              ❌ {error}
            </div>
          ))}
          <button onClick={clearErrors} style={{
            backgroundColor: '#dc3545',
            color: 'white',
            border: 'none',
            padding: '8px 16px',
            borderRadius: '4px'
          }}>
            Clear All Errors
          </button>
        </div>
      )}

      <div>
        <button onClick={addError} style={{ marginRight: '10px' }}>
          Add Error
        </button>
        <button onClick={() => setShowModal(true)}>
          Show Modal
        </button>
      </div>

      {/* Modal */}
      {showModal && (
        <div style={{
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          backgroundColor: 'rgba(0,0,0,0.5)',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          zIndex: 1000
        }}>
          <div style={{
            backgroundColor: 'white',
            padding: '30px',
            borderRadius: '8px',
            maxWidth: '400px',
            width: '90%'
          }}>
            <h3>Modal Title</h3>
            <p>This is a conditionally displayed modal.</p>
            <button
              onClick={() => setShowModal(false)}
              style={{
                backgroundColor: '#007bff',
                color: 'white',
                border: 'none',
                padding: '10px 20px',
                borderRadius: '4px'
              }}
            >
              Close
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

🎯 Complex Conditional Judgment

Switch Statement Simulation

jsx
function ComplexConditionals() {
  const [status, setStatus] = React.useState('idle');
  const [userRole, setUserRole] = React.useState('guest');
  const [errorType, setErrorType] = React.useState(null);

  // Status rendering function
  const renderStatus = () => {
    switch (status) {
      case 'loading':
        return (
          <div style={{ textAlign: 'center', color: '#007bff' }}>
            ⏳ Loading...
          </div>
        );
      case 'success':
        return (
          <div style={{ textAlign: 'center', color: '#28a745' }}>
            ✅ Operation completed successfully
          </div>
        );
      case 'error':
        return (
          <div style={{ textAlign: 'center', color: '#dc3545' }}>
            ❌ Operation failed, please retry
          </div>
        );
      case 'idle':
      default:
        return (
          <div style={{ textAlign: 'center', color: '#6c757d' }}>
            💤 Waiting for operation
          </div>
        );
    }
  };

  // User interface rendering
  const renderUserInterface = () => {
    const interfaces = {
      admin: (
        <div style={{ backgroundColor: '#e7f3ff', padding: '20px', borderRadius: '8px' }}>
          <h3>👑 Admin Console</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
            <button>User Management</button>
            <button>System Settings</button>
            <button>Data Statistics</button>
            <button>Security Center</button>
          </div>
        </div>
      ),
      moderator: (
        <div style={{ backgroundColor: '#fff3e0', padding: '20px', borderRadius: '8px' }}>
          <h3>🛡️ Moderator Panel</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
            <button>Content Review</button>
            <button>User Reports</button>
            <button>Community Management</button>
            <button>Data Reports</button>
          </div>
        </div>
      ),
      vip: (
        <div style={{ backgroundColor: '#f3e5f5', padding: '20px', borderRadius: '8px' }}>
          <h3>💎 VIP Area</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
            <button>Exclusive Service</button>
            <button>Advanced Features</button>
            <button>Priority Support</button>
            <button>Special Gifts</button>
          </div>
        </div>
      ),
      user: (
        <div style={{ backgroundColor: '#e8f5e8', padding: '20px', borderRadius: '8px' }}>
          <h3>👤 User Center</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
            <button>Profile</button>
            <button>Order Management</button>
            <button>Favorites</button>
            <button>Settings</button>
          </div>
        </div>
      ),
      guest: (
        <div style={{ backgroundColor: '#f8f9fa', padding: '20px', borderRadius: '8px' }}>
          <h3>🚪 Guest Mode</h3>
          <p>Please login for full functionality</p>
          <div style={{ display: 'flex', gap: '10px' }}>
            <button style={{ backgroundColor: '#007bff', color: 'white', border: 'none', padding: '10px 20px', borderRadius: '4px' }}>
              Login
            </button>
            <button style={{ backgroundColor: '#28a745', color: 'white', border: 'none', padding: '10px 20px', borderRadius: '4px' }}>
              Register
            </button>
          </div>
        </div>
      )
    };

    return interfaces[userRole] || interfaces.guest;
  };

  // Error type handling
  const renderError = () => {
    if (!errorType) return null;

    const errorMessages = {
      network: {
        icon: '🌐',
        title: 'Network Error',
        message: 'Please check your network connection',
        color: '#ff6b6b'
      },
      auth: {
        icon: '🔐',
        title: 'Authentication Failed',
        message: 'Please login again',
        color: '#ffa502'
      },
      permission: {
        icon: '🚫',
        title: 'Insufficient Permissions',
        message: 'You do not have permission to perform this action',
        color: '#ff4757'
      },
      server: {
        icon: '🔧',
        title: 'Server Error',
        message: 'Server is temporarily unavailable, please retry later',
        color: '#5f27cd'
      }
    };

    const error = errorMessages[errorType];

    return (
      <div style={{
        backgroundColor: error.color + '20',
        border: `1px solid ${error.color}`,
        borderRadius: '8px',
        padding: '15px',
        margin: '20px 0'
      }}>
        <div style={{ display: 'flex', alignItems: 'center', marginBottom: '10px' }}>
          <span style={{ fontSize: '24px', marginRight: '10px' }}>{error.icon}</span>
          <h4 style={{ margin: 0, color: error.color }}>{error.title}</h4>
        </div>
        <p style={{ margin: 0, color: '#333' }}>{error.message}</p>
        <button
          onClick={() => setErrorType(null)}
          style={{
            marginTop: '10px',
            backgroundColor: error.color,
            color: 'white',
            border: 'none',
            padding: '8px 16px',
            borderRadius: '4px'
          }}
        >
          Close
        </button>
      </div>
    );
  };

  return (
    <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
      <h2>Complex Conditional Judgment Demo</h2>

      {/* Status control */}
      <div style={{ marginBottom: '20px' }}>
        <h3>Status Control</h3>
        <div style={{ display: 'flex', gap: '10px', marginBottom: '15px' }}>
          {['idle', 'loading', 'success', 'error'].map(s => (
            <button
              key={s}
              onClick={() => setStatus(s)}
              style={{
                backgroundColor: status === s ? '#007bff' : '#f8f9fa',
                color: status === s ? 'white' : '#333',
                border: '1px solid #ddd',
                padding: '8px 16px',
                borderRadius: '4px'
              }}
            >
              {s}
            </button>
          ))}
        </div>
        {renderStatus()}
      </div>

      {/* User role switching */}
      <div style={{ marginBottom: '20px' }}>
        <h3>User Role</h3>
        <select
          value={userRole}
          onChange={(e) => setUserRole(e.target.value)}
          style={{ padding: '8px', marginBottom: '15px' }}
        >
          <option value="guest">Guest</option>
          <option value="user">Regular User</option>
          <option value="vip">VIP User</option>
          <option value="moderator">Moderator</option>
          <option value="admin">Admin</option>
        </select>
        {renderUserInterface()}
      </div>

      {/* Error type demo */}
      <div>
        <h3>Error Handling</h3>
        <div style={{ display: 'flex', gap: '10px', marginBottom: '15px' }}>
          {['network', 'auth', 'permission', 'server'].map(type => (
            <button
              key={type}
              onClick={() => setErrorType(type)}
              style={{
                backgroundColor: '#dc3545',
                color: 'white',
                border: 'none',
                padding: '8px 16px',
                borderRadius: '4px'
              }}
            >
              {type} Error
            </button>
          ))}
        </div>
        {renderError()}
      </div>
    </div>
  );
}

Multiple Condition Combinations

jsx
function MultipleConditions() {
  const [user, setUser] = React.useState({
    isLoggedIn: false,
    isVip: false,
    credits: 0,
    level: 1
  });

  const [appState, setAppState] = React.useState({
    isOnline: true,
    maintenance: false,
    feature: {
      chatEnabled: true,
      paymentEnabled: true,
      analyticsEnabled: false
    }
  });

  const toggleLogin = () => {
    setUser(prev => ({
      ...prev,
      isLoggedIn: !prev.isLoggedIn,
      credits: prev.isLoggedIn ? 0 : 150,
      level: prev.isLoggedIn ? 1 : 3
    }));
  };

  const toggleVip = () => {
    setUser(prev => ({ ...prev, isVip: !prev.isVip }));
  };

  const toggleMaintenance = () => {
    setAppState(prev => ({ ...prev, maintenance: !prev.maintenance }));
  };

  const canAccessFeature = (feature) => {
    return user.isLoggedIn &&
           appState.isOnline &&
           !appState.maintenance &&
           appState.feature[feature];
  };

  const canAccessVipFeature = () => {
    return user.isLoggedIn &&
           user.isVip &&
           user.level >= 3 &&
           appState.isOnline;
  };

  const showPaymentOptions = () => {
    return user.isLoggedIn &&
           user.credits < 100 &&
           canAccessFeature('paymentEnabled');
  };

  return (
    <div style={{ padding: '20px' }}>
      <h2>Multiple Condition Judgment</h2>

      {/* Control panel */}
      <div style={{
        backgroundColor: '#f8f9fa',
        padding: '15px',
        borderRadius: '8px',
        marginBottom: '20px'
      }}>
        <h3>Control Panel</h3>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px' }}>
          <button onClick={toggleLogin}>
            {user.isLoggedIn ? 'Logout' : 'Login'}
          </button>
          <button onClick={toggleVip} disabled={!user.isLoggedIn}>
            {user.isVip ? 'Cancel VIP' : 'Upgrade to VIP'}
          </button>
          <button onClick={toggleMaintenance}>
            {appState.maintenance ? 'End Maintenance' : 'Start Maintenance'}
          </button>
        </div>

        <div style={{ marginTop: '10px', fontSize: '14px' }}>
          <span>Online: {appState.isOnline ? '✅' : '❌'}</span>
          <span style={{ marginLeft: '20px' }}>
            Maintenance Mode: {appState.maintenance ? '🔧' : '✅'}
          </span>
        </div>
      </div>

      {/* User status display */}
      <div style={{ marginBottom: '20px' }}>
        {user.isLoggedIn ? (
          <div style={{
            backgroundColor: '#d4edda',
            padding: '15px',
            borderRadius: '8px',
            border: '1px solid #c3e6cb'
          }}>
            <h3>User Info</h3>
            <p>Status: Logged in {user.isVip && '👑 VIP'}</p>
            <p>Credits: {user.credits}</p>
            <p>Level: {user.level}</p>
          </div>
        ) : (
          <div style={{
            backgroundColor: '#f8d7da',
            padding: '15px',
            borderRadius: '8px',
            border: '1px solid #f5c6cb'
          }}>
            <h3>Not Logged In</h3>
            <p>Please login to use all features</p>
          </div>
        )}
      </div>

      {/* Maintenance mode reminder */}
      {appState.maintenance && (
        <div style={{
          backgroundColor: '#fff3cd',
          border: '1px solid #ffeaa7',
          padding: '15px',
          borderRadius: '8px',
          marginBottom: '20px'
        }}>
          🔧 System is under maintenance, some features may be unavailable
        </div>
      )}

      {/* Feature areas */}
      <div style={{
        display: 'grid',
        gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
        gap: '15px'
      }}>
        {/* Chat feature */}
        <div style={{
          border: '1px solid #ddd',
          borderRadius: '8px',
          padding: '15px',
          opacity: canAccessFeature('chatEnabled') ? 1 : 0.5
        }}>
          <h4>💬 Chat Feature</h4>
          {canAccessFeature('chatEnabled') ? (
            <div>
              <p>Chat feature is available</p>
              <button>Start Chat</button>
            </div>
          ) : (
            <div>
              <p style={{ color: '#666' }}>
                {!user.isLoggedIn && 'Please login first'}
                {user.isLoggedIn && appState.maintenance && 'Temporarily unavailable during maintenance'}
                {user.isLoggedIn && !appState.feature.chatEnabled && 'Feature has been disabled'}
              </p>
            </div>
          )}
        </div>

        {/* VIP feature */}
        <div style={{
          border: '1px solid #ddd',
          borderRadius: '8px',
          padding: '15px',
          opacity: canAccessVipFeature() ? 1 : 0.5
        }}>
          <h4>👑 VIP Exclusive Feature</h4>
          {canAccessVipFeature() ? (
            <div>
              <p>VIP feature is available</p>
              <button>Access VIP Area</button>
            </div>
          ) : (
            <div>
              <p style={{ color: '#666' }}>
                {!user.isLoggedIn && 'Please login first'}
                {user.isLoggedIn && !user.isVip && 'VIP membership required'}
                {user.isLoggedIn && user.isVip && user.level < 3 && 'Insufficient level'}
                {user.isLoggedIn && user.isVip && !appState.isOnline && 'Network unavailable'}
              </p>
            </div>
          )}
        </div>

        {/* Payment options */}
        <div style={{
          border: '1px solid #ddd',
          borderRadius: '8px',
          padding: '15px',
          opacity: showPaymentOptions() ? 1 : 0.5
        }}>
          <h4>💳 Recharge Center</h4>
          {showPaymentOptions() ? (
            <div>
              <p>Insufficient credits, need to recharge</p>
              <button>Recharge Now</button>
            </div>
          ) : user.isLoggedIn && user.credits >= 100 ? (
            <div>
              <p style={{ color: 'green' }}>Sufficient credits</p>
            </div>
          ) : (
            <div>
              <p style={{ color: '#666' }}>
                {!user.isLoggedIn && 'Please login first'}
                {user.isLoggedIn && !canAccessFeature('paymentEnabled') && 'Payment feature unavailable'}
              </p>
            </div>
          )}
        </div>
      </div>

      {/* Condition combination examples */}
      <div style={{ marginTop: '30px' }}>
        <h3>Condition Combination Examples</h3>
        <div style={{ fontSize: '14px', backgroundColor: '#f8f9fa', padding: '15px', borderRadius: '8px' }}>
          <p><strong>Chat feature condition:</strong> loggedIn && online && !maintenance && featureEnabled</p>
          <p><strong>VIP feature condition:</strong> loggedIn && vipMember && level≥3 && online</p>
          <p><strong>Recharge prompt condition:</strong> loggedIn && credits<100 && paymentEnabled</p>
        </div>
      </div>
    </div>
  );
}

📝 Chapter Summary

Through this chapter, you should have mastered:

Conditional Judgment Methods

  • ✅ if statement: Suitable for complex logic
  • ✅ Ternary operator: Concise binary judgment
  • ✅ Logical AND operator: Simple existence check
  • ✅ Switch simulation: Multi-branch condition handling

Best Practices

  1. Choose appropriate methods: Select judgment method based on complexity
  2. Avoid deep nesting: Use early returns and extract functions
  3. Condition combination: Reasonably organize multiple condition logic
  4. Performance optimization: Avoid unnecessary condition calculations
  5. Readability first: Keep code clear and understandable

Continue Learning: Next Chapter - React Custom Hook

Content is for learning and research only.