Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 74

Conditional Rendering for Authentication Status

Recommended resources

Hello! Welcome back to the "Full-Stack User Authentication" module.

In our last lesson, you did an excellent job learning how to protect entire pages using ProtectedRoute components. By leveraging our useAuth hook and the React Router <Outlet> pattern, we can now effectively lock down routes and redirect unauthenticated users.

Today, we'll zoom in from page-level security to element-level UI control. Our goal is to conditionally render UI elements based on the user's authentication status. This means showing or hiding specific parts of your interfaceโ€”like a "Login" button for guests versus a "Logout" button for usersโ€”all based on that same user object from our authentication context. This is a fundamental skill for building dynamic and user-friendly applications.

Conditional Rendering in React Thumbnail
This image visually represents the core idea of conditional rendering: based on a condition, your application chooses between different UI outputs.

The Core Techniques of Conditional Rendering

At its heart, conditional rendering in React is just using standard JavaScript logic to decide what JSX gets returned. There are three main ways to achieve this.

To see the first two techniques in action, let's start with a short, focused video.

How to CONDITIONAL RENDER in React โ“

The video 'How to CONDITIONAL RENDER in React โ“' from the Bro Code channel provides a great introduction to the most common patterns. We'll focus on the if/else and ternary operator approaches first.

Please watch from 01:42 to 04:36. Pay attention to: How if/else statements are used within the component function but before the final return statement. How the ternary operator (? :) allows you to write this same logic concisely, directly inside your JSX.

Let's summarize and apply these patterns to our authentication use case.

1. Using if/else Statements

As the video showed, a simple if/else block is a perfectly valid way to control what a component renders. You use your useAuth hook to get the user, and then return different JSX blocks based on whether the user object exists.

import useAuth from './hooks/useAuth';

function UserStatus() {
  const { user } = useAuth();

  if (user) {
    return <p>Welcome back, {user.username}!</p>;
  } else {
    return <p>Please log in to continue.</p>;
  }
}

This is very clear and readable, but it can be a bit verbose if you only want to change a small part of a larger component.

2. Using the Ternary Operator

The ternary operator (condition ? expressionIfTrue : expressionIfFalse) is often the preferred method for inline conditional rendering inside JSX. It's concise and powerful.

Hereโ€™s how you could build a Header component that shows either a "Login" link or a "Logout" button:

import useAuth from './hooks/useAuth';
import { NavLink } from 'react-router-dom';

function Header() {
  const { user, logout } = useAuth(); // Assuming logout is provided by your AuthContext

  return (
    <nav>
      <NavLink to="/">Home</NavLink>
      {user ? (
        // Renders if 'user' is truthy (user is logged in)
        <>
          <span>Hello, {user.username}</span>
          <button onClick={logout}>Logout</button>
        </>
      ) : (
        // Renders if 'user' is falsy (user is null/logged out)
        <NavLink to="/login">Login</NavLink>
      )}
    </nav>
  );
}

This is extremely common in React development and is a pattern you will use constantly.


A Practical Example: Building a User-Aware Header

Let's look at a more complete, real-world example. The following article details how to build an authentication system, and includes a great section on conditionally rendering a header based on the user's login status. It even accounts for a "loading" state while the app is first checking for a user.

The React Mega-Tutorial, Chapter 8: Authentication

The 'User Information in the Header' section of 'The React Mega-Tutorial, Chapter 8: Authentication' provides an excellent, practical code example of what we're learning.

Please read the section titled 'User Information in the Header'. Focus on the Header.js code block. Notice how it handles three states: user === undefined: The app is still fetching user data (a spinner is shown). user: The user is logged in (a dropdown with their avatar is shown). user is null: The user is logged out (nothing is shown in that spot).

This example from Miguel Grinberg's tutorial is a perfect illustration of how to build a robust UI that gracefully handles different authentication states.


A Powerful Shortcut: The Logical && Operator

What if you only want to render something if a condition is true, and render nothing otherwise? You could use a ternary and return null in the else case:

{user ? <ProfileButton /> : null}

However, JavaScript offers a more concise shortcut: the logical AND (&&) operator.

The logic works because in JavaScript, true && expression always evaluates to expression, and false && expression always evaluates to false. React doesn't render false, null, or undefined, so the pattern works perfectly for "show or show nothing" logic.

import useAuth from './hooks/useAuth';

function Header() {
  const { user } = useAuth();

  return (
    <header>
      <h1>My App</h1>
      {/* The ProfileButton will only be rendered if a user exists */}
      {user && <ProfileButton username={user.username} />}
    </header>
  );
}

A Critical "Gotcha" with &&

The && operator is great, but it has a famous trap for junior developers. What happens if the left-hand side of the expression is not a boolean true or false, but a "falsy" value like the number 0?

This next short video explains the problem and how to avoid it.

Stop Conditional Rendering in React Without Knowing This (&& vs Ternary Operator)

The video 'Stop Conditional Rendering in React Without Knowing This' from ByteGrad clearly explains a common bug when using the && operator and how to write safer conditional logic.

Please watch from 00:39 to 02:59. The key takeaways are: How the && operator can accidentally render the number 0 in your UI. Two simple ways to prevent this: using an explicit boolean comparison (e.g., count > 0) or coercing the value to a boolean with a double negation (!!).

This is an important lesson. When a variable might be a number (like unreadMessagesCount), using count > 0 && <Component /> is much safer than count && <Component />.

Test your understanding!

You are building an e-commerce shopping cart. You have a variable itemsInCart which holds the number of items. You want to display a "Proceed to Checkout" button only if there is at least one item in the cart.

Here is the code:
{itemsInCart && <button>Proceed to Checkout</button>}

What potential bug exists here? How would you fix it using both methods discussed in the video?

Show answer

The bug is that if itemsInCart is 0, the expression 0 && <button>...</button> will evaluate to 0, and React will render the number 0 on the page instead of nothing.

Fix 1: Explicit Comparison (Recommended)
This is the clearest and most readable solution.

{itemsInCart > 0 && <button>Proceed to Checkout</button>}

Fix 2: Double Negation
This coerces itemsInCart to a true boolean (true for any non-zero number, false for 0).

{!!itemsInCart && <button>Proceed to Checkout</button>}

Conclusion

You now have a complete toolkit for controlling your UI based on authentication status, from entire pages down to single buttons. This combination of global state via Context and conditional rendering is at the heart of modern, interactive web applications.

Key Takeaways:

  • Ternary Operator (? :): Your go-to tool for inline conditional rendering when you need to provide an if/else choice (e.g., show "Login" or "Logout").
  • Logical AND (&&): A concise shortcut for rendering an element only when a condition is true.
  • The 0 Gotcha: Be cautious when using && with variables that could be the number 0. Prefer explicit boolean comparisons like count > 0 for safety and clarity.
  • Authentication Context is Key: All these rendering patterns are powered by the user object you get from your useAuth hook, which provides the condition to check against.

Preview of the Next Lesson:
We've covered protecting routes (UI access) and conditionally rendering elements (UI appearance). The final piece of the authentication puzzle is integrating it with our data operations. In the next lesson, we will integrate authentication with CRUD operations to enforce user-specific permissions. This means ensuring that a user can, for example, only edit or delete their own tasks in a task manager app, taking our security from the frontend to the backend.