dev.log / syntax diaries

Practical code notes, tools, and guided learning for developers.

Practical guides, developer tools, and tutorials for modern web developers, with the same focused tone across writing, utilities, and learning tracks.

BlogToolsTutorialsAboutContactAdmin Login
Privacy PolicyTerms of ServiceCookie Policy

ยฉ 2026 The Syntax Diaries ยท System_Operational

The Syntax Diaries logoThe Syntax Diaries
BlogToolsTutorialsAbout
build log live
Tutorial / React
State And Events25 minbeginner

Conditional Rendering

Learn how to show or hide content based on conditions, making your React components truly dynamic and responsive to user interactions.

On This Page

Why Do We Need Conditional Rendering?The Problem Without Conditional RenderingSolution 1: The Simple If StatementLet's Build Something TogetherStep 1: Set Up the Basic ComponentStep 2: Add Basic Conditional LogicThe Ternary Operator: Your New Best FriendThe Logical AND Operator: Show or NothingReal-World Example: Shopping CartAdvanced Conditional PatternsPattern 1: Multiple Conditions with FunctionsPattern 2: Conditional Classes and StylesPractice Exercise: Build a Weather WidgetCommon Conditional Rendering MistakesMistake 1: Forgetting About Falsy ValuesMistake 2: Not Handling Loading StatesMistake 3: Overly Complex Conditions in JSXWhen to Use Each PatternUse if statements when:Use ternary operators when:Use logical AND when:What We've LearnedQuick Recap QuizWhat's Next?

Conditional Rendering#

Imagine you're building a login page. When a user is logged in, you want to show "Welcome back, John!" but when they're not logged in, you want to show "Please sign in." This is conditional rendering - showing different content based on certain conditions.

Think of it like a traffic light for your UI:

  • ๐Ÿ”ด If user is not logged in โ†’ Show login form
  • ๐ŸŸข If user is logged in โ†’ Show welcome message
  • ๐ŸŸก If user is loading โ†’ Show loading spinner

This is one of the most powerful features in React, and you'll use it in almost every component you build!

Why Do We Need Conditional Rendering?#

Let's start with a real-world problem. Imagine you're building a simple weather app:

function WeatherApp() {
  const [weather, setWeather] = useState(null);
  
  return (
    <div>
      <h1>Weather App</h1>
      <p>Temperature: {weather.temperature}ยฐF</p>  {/* This will crash! */}
      <p>Condition: {weather.condition}</p>
    </div>
  );
}

What's wrong here? When the component first loads, "weather" is "null", so trying to access "weather.temperature" will cause an error!

We need a way to say: "Only show the weather information IF we actually have weather data."

The Problem Without Conditional Rendering#

Here's what happens without proper conditional rendering:

function UserProfile() {
  const [user, setUser] = useState(null); // Starts as null
  
  return (
    <div>
      <h1>User Profile</h1>
      <p>Name: {user.name}</p>        {/* Error! */}
      <p>Email: {user.email}</p>      {/* Error! */}
    </div>
  );
}

This component will immediately crash because "user" is "null" at first, and we can't access properties of "null".

Solution 1: The Simple If Statement#

The most basic way to handle this is with a simple if statement:

function UserProfile() {
  const [user, setUser] = useState(null);
  
  // If no user, show loading message
  if (!user) {
    return <p>Loading user profile...</p>;
  }
  
  // If we have a user, show their info
  return (
    <div>
      <h1>User Profile</h1>
      <p>Name: {user.name}</p>
      <p>Email: {user.email}</p>
    </div>
  );
}

What's happening here?

  1. We check if "user" is null or undefined
  2. If it is, we return early with a loading message
  3. If we have user data, we show the profile
  4. This prevents any crashes!

Let's Build Something Together#

Let's create a simple login system to understand conditional rendering step by step.

Step 1: Set Up the Basic Component#

function LoginSystem() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [username, setUsername] = useState("");
  
  return (
    <div>
      <h1>My App</h1>
      {/* We'll add conditional content here */}
    </div>
  );
}

Step 2: Add Basic Conditional Logic#

function LoginSystem() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [username, setUsername] = useState("");
  
  if (isLoggedIn) {
    return (
      <div>
        <h1>Welcome back, {username}!</h1>
        <button onClick={() => setIsLoggedIn(false)}>
          Logout
        </button>
      </div>
    );
  }
  
  return (
    <div>
      <h1>Please Sign In</h1>
      <input 
        type="text" 
        placeholder="Enter username"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <button onClick={() => setIsLoggedIn(true)}>
        Login
      </button>
    </div>
  );
}

Try it in your mind: What happens when you click the Login button? What about the Logout button?

This works great, but returning completely different JSX can make components hard to manage. Let's learn better approaches!

The Ternary Operator: Your New Best Friend#

The ternary operator is like a compact if-else statement that works inside JSX. The syntax is:

condition ? "Show this if true" : "Show this if false"

Let's rewrite our login system using the ternary operator:

function LoginSystem() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [username, setUsername] = useState("");
  
  return (
    <div>
      <h1>My App</h1>
      
      {isLoggedIn ? (
        // Show this if logged in
        <div>
          <p>Welcome back, {username}!</p>
          <button onClick={() => setIsLoggedIn(false)}>
            Logout
          </button>
        </div>
      ) : (
        // Show this if not logged in
        <div>
          <input 
            type="text" 
            placeholder="Enter username"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
          />
          <button onClick={() => setIsLoggedIn(true)}>
            Login
          </button>
        </div>
      )}
    </div>
  );
}

Benefits of this approach:

  • Everything stays in one return statement
  • Easier to see the overall component structure
  • More flexible for complex layouts

The Logical AND Operator: Show or Nothing#

Sometimes you don't need an "else" case - you just want to show something or show nothing. That's where the logical AND ("&&") operator shines:

function NotificationBell() {
  const [hasNewMessages, setHasNewMessages] = useState(true);
  const [messageCount, setMessageCount] = useState(3);
  
  return (
    <div>
      <h2>๐Ÿ”” Notifications</h2>
      
      {hasNewMessages && (
        <div className="notification-badge">
          You have {messageCount} new messages!
        </div>
      )}
      
      <button onClick={() => setHasNewMessages(!hasNewMessages)}>
        Toggle Notifications
      </button>
    </div>
  );
}

How it works:

  • If "hasNewMessages" is "true", React shows the notification
  • If "hasNewMessages" is "false", React shows nothing
  • It's perfect for "show or hide" scenarios

Real-World Example: Shopping Cart#

Let's build a shopping cart component that demonstrates multiple conditional rendering patterns:

function ShoppingCart() {
  const [items, setItems] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [showCart, setShowCart] = useState(false);
  
  const addItem = (itemName) => {
    setItems([...items, { id: Date.now(), name: itemName, price: 19.99 }]);
  };
  
  const removeItem = (itemId) => {
    setItems(items.filter(item => item.id !== itemId));
  };
  
  const getTotalPrice = () => {
    return items.reduce((total, item) => total + item.price, 0).toFixed(2);
  };
  
  return (
    <div style={{ padding: "20px" }}>
      <h1>๐Ÿ›’ Shopping Cart Demo</h1>
      
      {/* Show/Hide Cart Button */}
      <button onClick={() => setShowCart(!showCart)}>
        {showCart ? "Hide Cart" : "Show Cart"} ({items.length} items)
      </button>
      
      {/* Quick Add Buttons */}
      <div style={{ margin: "10px 0" }}>
        <button onClick={() => addItem("Cool T-Shirt")}>Add T-Shirt</button>
        <button onClick={() => addItem("Nice Shoes")}>Add Shoes</button>
        <button onClick={() => addItem("Awesome Hat")}>Add Hat</button>
      </div>
      
      {/* Cart Content - Only show if showCart is true */}
      {showCart && (
        <div style={{ 
          border: "2px solid #ccc", 
          padding: "15px", 
          marginTop: "10px",
          borderRadius: "5px"
        }}>
          <h2>Your Cart</h2>
          
          {/* Loading State */}
          {isLoading ? (
            <p>Loading cart...</p>
          ) : (
            <div>
              {/* Empty Cart vs Items */}
              {items.length === 0 ? (
                <p>Your cart is empty. Add some items!</p>
              ) : (
                <div>
                  <ul>
                    {items.map(item => (
                      <li key={item.id} style={{ 
                        display: "flex", 
                        justifyContent: "space-between",
                        alignItems: "center",
                        padding: "5px 0"
                      }}>
                        <span>{item.name} - $" + item.price + "</span>
                        <button onClick={() => removeItem(item.id)}>
                          Remove
                        </button>
                      </li>
                    ))}
                  </ul>
                  
                  <div style={{ 
                    marginTop: "15px", 
                    fontSize: "18px", 
                    fontWeight: "bold" 
                  }}>
                    Total: $" + getTotalPrice() + "
                  </div>
                  
                  {/* Show checkout button only if cart has items */}
                  {items.length > 0 && (
                    <button style={{ 
                      backgroundColor: "#4CAF50", 
                      color: "white",
                      padding: "10px 20px",
                      marginTop: "10px",
                      border: "none",
                      borderRadius: "5px"
                    }}>
                      Checkout
                    </button>
                  )}
                </div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

What conditional rendering patterns do you see?

  1. Ternary operator for button text: "showCart ? 'Hide Cart' : 'Show Cart'"
  2. Logical AND for showing cart: "showCart && <div>...</div>"
  3. Ternary operator for loading vs content: "isLoading ? <Loading/> : <Content/>"
  4. Ternary operator for empty vs filled cart: "items.length === 0 ? <Empty/> : <Items/>"
  5. Logical AND for checkout button: "items.length > 0 && <button>Checkout</button>"

Advanced Conditional Patterns#

Pattern 1: Multiple Conditions with Functions#

Sometimes you have complex logic that's hard to read in JSX. Extract it to a function:

function UserStatus({ user }) {
  const renderUserStatus = () => {
    if (!user) {
      return <p>No user found</p>;
    }
    
    if (user.isOnline && user.isActive) {
      return <span style={{color: "green"}}>๐ŸŸข Online & Active</span>;
    }
    
    if (user.isOnline) {
      return <span style={{color: "orange"}}>๐ŸŸก Online but Away</span>;
    }
    
    if (user.lastSeen) {
      return <span style={{color: "gray"}}>๐Ÿ”ด Last seen: {user.lastSeen}</span>;
    }
    
    return <span style={{color: "red"}}>๐Ÿ”ด Offline</span>;
  };
  
  return (
    <div>
      <h3>User Status</h3>
      {renderUserStatus()}
    </div>
  );
}

Pattern 2: Conditional Classes and Styles#

You can conditionally apply CSS classes and styles:

function Message({ type, children }) {
  return (
    <div 
      className={type === "error" ? "error-message" : "info-message"}
      style={{
        padding: "10px",
        borderRadius: "5px",
        backgroundColor: type === "error" ? "#ffebee" : "#e3f2fd",
        color: type === "error" ? "#c62828" : "#1565c0",
        border: type === "error" ? "1px solid #e57373" : "1px solid #64b5f6"
      }}
    >
      {type === "error" ? "โŒ" : "โ„น๏ธ"} {children}
    </div>
  );
}

// Usage:
<Message type="error">Something went wrong!</Message>
<Message type="info">Here's some helpful information.</Message>

Practice Exercise: Build a Weather Widget#

Let's put your conditional rendering skills to the test! Try building this weather widget:

Requirements:

  1. Start with no weather data (null)
  2. Have a "Get Weather" button
  3. Show loading state when fetching
  4. Show weather info when loaded
  5. Show different icons based on weather condition
  6. Handle error states

Here's the starter code:

function WeatherWidget() {
  const [weather, setWeather] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  
  const getWeather = () => {
    setIsLoading(true);
    setError(null);
    
    // Simulate API call
    setTimeout(() => {
      // Randomly succeed or fail for demo
      if (Math.random() > 0.3) {
        setWeather({
          temperature: Math.round(Math.random() * 30 + 50), // 50-80ยฐF
          condition: ["sunny", "cloudy", "rainy"][Math.floor(Math.random() * 3)],
          city: "New York"
        });
      } else {
        setError("Failed to fetch weather data");
      }
      setIsLoading(false);
    }, 2000);
  };
  
  // Your code here! Use conditional rendering to:
  // 1. Show loading spinner when isLoading is true
  // 2. Show error message if error exists
  // 3. Show weather data if weather exists
  // 4. Show "Get Weather" button if no weather data
  
  return (
    <div style={{ padding: "20px", textAlign: "center" }}>
      <h2>๐ŸŒค๏ธ Weather Widget</h2>
      {/* Add your conditional rendering here */}
    </div>
  );
}

Solution (try it yourself first!):

function WeatherWidget() {
  const [weather, setWeather] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  
  const getWeather = () => {
    setIsLoading(true);
    setError(null);
    
    setTimeout(() => {
      if (Math.random() > 0.3) {
        setWeather({
          temperature: Math.round(Math.random() * 30 + 50),
          condition: ["sunny", "cloudy", "rainy"][Math.floor(Math.random() * 3)],
          city: "New York"
        });
      } else {
        setError("Failed to fetch weather data");
      }
      setIsLoading(false);
    }, 2000);
  };
  
  const getWeatherIcon = (condition) => {
    switch(condition) {
      case "sunny": return "โ˜€๏ธ";
      case "cloudy": return "โ˜๏ธ";
      case "rainy": return "๐ŸŒง๏ธ";
      default: return "๐ŸŒค๏ธ";
    }
  };
  
  const reset = () => {
    setWeather(null);
    setError(null);
  };
  
  return (
    <div style={{ padding: "20px", textAlign: "center" }}>
      <h2>๐ŸŒค๏ธ Weather Widget</h2>
      
      {isLoading ? (
        // Loading state
        <div>
          <p>๐Ÿ”„ Getting weather data...</p>
          <div>Loading...</div>
        </div>
      ) : error ? (
        // Error state
        <div>
          <p style={{ color: "red" }}>โŒ {error}</p>
          <button onClick={getWeather}>Try Again</button>
        </div>
      ) : weather ? (
        // Weather data loaded
        <div style={{
          backgroundColor: "#f0f8ff",
          padding: "20px",
          borderRadius: "10px",
          margin: "10px 0"
        }}>
          <h3>{weather.city}</h3>
          <div style={{ fontSize: "48px" }}>
            {getWeatherIcon(weather.condition)}
          </div>
          <p style={{ fontSize: "24px", margin: "10px 0" }}>
            {weather.temperature}ยฐF
          </p>
          <p style={{ textTransform: "capitalize" }}>
            {weather.condition}
          </p>
          <button onClick={reset} style={{ marginTop: "10px" }}>
            Get New Weather
          </button>
        </div>
      ) : (
        // Initial state - no weather data
        <div>
          <p>Click to get current weather information</p>
          <button onClick={getWeather}>Get Weather</button>
        </div>
      )}
    </div>
  );
}

Common Conditional Rendering Mistakes#

Mistake 1: Forgetting About Falsy Values#

// โŒ This will show "0" when count is 0
{count && <p>Count: {count}</p>}

// โœ… Be explicit with your conditions
{count > 0 && <p>Count: {count}</p>}
{count !== 0 && <p>Count: {count}</p>}

Mistake 2: Not Handling Loading States#

// โŒ Users see nothing while data loads
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  
  return (
    <div>
      {user && (
        <div>
          <h1>{user.name}</h1>
          <p>{user.email}</p>
        </div>
      )}
    </div>
  );
}

// โœ… Always handle loading states
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  
  return (
    <div>
      {isLoading ? (
        <p>Loading user profile...</p>
      ) : user ? (
        <div>
          <h1>{user.name}</h1>
          <p>{user.email}</p>
        </div>
      ) : (
        <p>User not found</p>
      )}
    </div>
  );
}

Mistake 3: Overly Complex Conditions in JSX#

// โŒ Hard to read and maintain
{user && user.profile && user.profile.settings && user.profile.settings.notifications && user.profile.settings.notifications.email ? (
  <EmailNotificationSettings />
) : (
  <DefaultSettings />
)}

// โœ… Extract complex logic to variables or functions
const canShowEmailSettings = user?.profile?.settings?.notifications?.email;

return (
  <div>
    {canShowEmailSettings ? (
      <EmailNotificationSettings />
    ) : (
      <DefaultSettings />
    )}
  </div>
);

When to Use Each Pattern#

Use if statements when:#

  • You need to return completely different components
  • You have complex logic that would make JSX hard to read
  • You're doing early returns for error/loading states

Use ternary operators when:#

  • You have a clear "this or that" choice
  • Both options are relatively simple
  • You want to keep everything in the JSX return

Use logical AND when:#

  • You want to show something or nothing
  • The condition is simple
  • You're toggling visibility of elements

What We've Learned#

Congratulations! You now know how to:

โœ… Show different content based on conditions
โœ… Handle loading, error, and success states
โœ… Use ternary operators for either/or scenarios
โœ… Use logical AND for show/hide scenarios
โœ… Build complex conditional UIs
โœ… Avoid common conditional rendering pitfalls

Quick Recap Quiz#

Test your understanding:

  1. What's the difference between "&&" and "? :" for conditional rendering?
  2. Why might "{count && <p>Count: {count}</p>}" cause problems?
  3. When should you extract conditional logic to a separate function?
  4. How do you handle multiple possible states (loading, error, success)?

Answers: 1) && shows something or nothing, ?: shows one thing or another, 2) Shows "0" when count is 0, 3) When logic is complex or repeated, 4) Use nested ternary operators or if-else chains

What's Next?#

In our next lesson, we'll learn about Lists and Keys - how to render multiple items dynamically and why React needs special "key" props. You'll discover how to build dynamic lists, handle user interactions with list items, and optimize list performance.

Combined with conditional rendering, lists will let you build truly dynamic and interactive user interfaces!

Previous

React Router

Next

Event Handling