React Conditional Rendering

React applications often need to display different content depending on what is happening in the application.

For example:

  • Show a login button when a user is logged out.
  • Show a dashboard when the user is logged in.
  • Display a loading message while data is being fetched.
  • Display an error message when something goes wrong.
  • Show a success message after a form is submitted.
  • Display different components based on a user’s role.
  • Show or hide an element based on a condition.

This is called conditional rendering.

Conditional rendering means rendering different JSX depending on whether a condition is true or false.

React uses normal JavaScript techniques for conditional rendering. You can use if statements, ternary operators, logical &&, early returns, and other JavaScript expressions to decide what should appear on the screen.

For example:

function App() {
  const isLoggedIn = true;

  if (isLoggedIn) {
    return <h1>Welcome back!</h1>;
  }

  return <h1>Please log in.</h1>;
}

export default App;

When isLoggedIn is true, React displays:

Welcome back!

When it is false, React displays:

Please log in.

Understanding conditional rendering is essential because almost every real-world React application needs to change its UI based on data, state, user actions, or application status.

What Is Conditional Rendering?

Conditional rendering is the process of displaying different UI depending on a condition.

The basic idea is:

Condition
   ↓
Is it true?
   ↓
Yes → Render one UI
No  → Render another UI

For example:

function App() {
  const isLoggedIn = false;

  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome!</h1>
      ) : (
        <h1>Please log in.</h1>
      )}
    </div>
  );
}

export default App;

Because isLoggedIn is false, React renders:

Please log in.

If the value changes to true, React renders:

Welcome!

Why Is Conditional Rendering Important?

A modern application rarely displays exactly the same interface all the time.

Consider an online shopping website.

When a user visits the website, the application might show:

Loading products...

After the products load:

Laptop
Keyboard
Mouse

If the request fails:

Unable to load products.

If there are no products:

No products found.

The UI changes based on the application’s current state.

Conditional rendering allows React to represent these different states clearly.

Common situations include:

  • Authentication
  • Loading states
  • Error states
  • Empty states
  • Permissions
  • User roles
  • Form validation
  • Navigation
  • Search results
  • Shopping carts
  • Notifications
  • Feature availability

How Conditional Rendering Works in React

React does not have a special if rendering syntax.

Instead, React uses JavaScript conditions to determine which JSX should be returned.

For example:

function Greeting() {
  const isLoggedIn = true;

  if (isLoggedIn) {
    return <h2>Welcome back!</h2>;
  }

  return <h2>Please log in.</h2>;
}

The JavaScript condition determines which JSX React receives.

You can think of it as:

JavaScript condition
       ↓
Choose JSX
       ↓
React renders JSX

There are several common approaches.

Using if Statements

An if statement is one of the easiest ways to understand conditional rendering.

function Greeting() {
  const isLoggedIn = true;

  if (isLoggedIn) {
    return <h1>Welcome back!</h1>;
  }

  return <h1>Please log in.</h1>;
}

export default Greeting;

Here, React checks:

if (isLoggedIn)

If the condition is true, the first return executes.

If the condition is false, the second return executes.

Understanding the Example

Suppose:

const isLoggedIn = true;

The condition becomes:

if (true)

Therefore:

<h1>Welcome back!</h1>

is rendered.

If:

const isLoggedIn = false;

the condition becomes:

if (false)

and React renders:

<h1>Please log in.</h1>

Using if...else

You can also write:

function App() {
  const isAdmin = true;

  if (isAdmin) {
    return <h1>Admin Dashboard</h1>;
  } else {
    return <h1>User Dashboard</h1>;
  }
}

export default App;

The else block runs when the condition is false.

When Should You Use if?

if statements are particularly useful when:

  • The logic is complex.
  • You have several conditions.
  • You need to perform calculations before rendering.
  • You want an early return.
  • Different conditions produce substantially different UI.

For simple inline conditions, a ternary operator or && can often be shorter.

The Ternary Operator

The ternary operator is one of the most common ways to conditionally render JSX.

Its basic syntax is:

condition ? valueIfTrue : valueIfFalse

For example:

function App() {
  const isLoggedIn = true;

  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome!</h1>
      ) : (
        <h1>Please log in.</h1>
      )}
    </div>
  );
}

export default App;

The condition is:

isLoggedIn

If it is true:

<h1>Welcome!</h1>

is rendered.

If it is false:

<h1>Please log in.</h1>

is rendered.

Simple Ternary Example

A ternary can also be used for small pieces of text.

function App() {
  const isOnline = true;

  return (
    <p>
      Status: {isOnline ? "Online" : "Offline"}
    </p>
  );
}

export default App;

Ternary with Buttons

function App() {
  const isLoggedIn = false;

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

export default App;

Ternary with Components

You can conditionally render entire components.

function App() {
  const isLoggedIn = true;

  return (
    <div>
      {isLoggedIn ? <Dashboard /> : <Login />}
    </div>
  );
}

This is useful when two different components represent two different application states.

Logical && Rendering

The logical AND operator, &&, is useful when you want to render something only when a condition is true.

Example:

function App() {
  const isLoggedIn = true;

  return (
    <div>
      {isLoggedIn && <p>Welcome back!</p>}
    </div>
  );
}

export default App;

If isLoggedIn is true, React renders:

Welcome back!

If it is false, React renders nothing for that expression.

Understanding the Logic

JavaScript evaluates:

true && "Hello"

as:

Hello

But:

false && "Hello"

results in:

false

React does not render the boolean false as visible text.

Therefore:

{isLoggedIn && <Dashboard />}

means:

Render <Dashboard /> only if isLoggedIn is truthy.

Showing Notifications

function App() {
  const hasNotification = true;

  return (
    <div>
      <h1>Dashboard</h1>

      {hasNotification && (
        <p>You have new notifications.</p>
      )}
    </div>
  );
}

export default App;

Showing an Element Based on State

import { useState } from "react";

function App() {
  const [showMessage, setShowMessage] = useState(false);

  return (
    <div>
      <button onClick={() => setShowMessage(!showMessage)}>
        Toggle Message
      </button>

      {showMessage && (
        <p>This message is visible.</p>
      )}
    </div>
  );
}

export default App;

When the button is clicked, the state changes and React updates the UI.

An Important && Gotcha

Be careful when the value on the left side can be 0.

For example:

function App() {
  const messageCount = 0;

  return (
    <div>
      {messageCount && <p>You have messages.</p>}
    </div>
  );
}

The expression evaluates to:

0

Unlike false, null, or undefined, React can render the number 0.

You may therefore see 0 on the screen.

A safer approach is:

{messageCount > 0 && (
  <p>You have messages.</p>
)}

Now the condition explicitly checks whether there are messages.

This is an important detail to remember when using && with numbers.

Multiple Conditions

Real applications often have more than two possible states.

For example, a user might be:

  • An administrator
  • A regular user
  • A guest

You can use multiple conditions to render the appropriate UI.

Using if Statements

function Dashboard({ role }) {
  if (role === "admin") {
    return <h1>Admin Dashboard</h1>;
  }

  if (role === "user") {
    return <h1>User Dashboard</h1>;
  }

  return <h1>Guest Area</h1>;
}

export default Dashboard;

This is usually easier to read than deeply nested ternary expressions.

Multiple Ternary Conditions

You can technically write:

function App({ role }) {
  return (
    <div>
      {role === "admin" ? (
        <AdminPanel />
      ) : role === "user" ? (
        <UserPanel />
      ) : (
        <GuestPanel />
      )}
    </div>
  );
}

This works, but deeply nested ternaries can become difficult to read.

For more complex logic, an if statement or another approach may be clearer.

Using Logical Operators for Multiple Conditions

You can combine conditions with JavaScript operators.

For example:

function App({ isLoggedIn, isAdmin }) {
  return (
    <div>
      {isLoggedIn && isAdmin && (
        <button>Admin Settings</button>
      )}
    </div>
  );
}

The button appears only when both conditions are true.

This is equivalent to:

Logged in?
   ↓
Yes
   ↓
Administrator?
   ↓
Yes
   ↓
Show Admin Settings

Conditional Components

Sometimes the condition determines which entire component should appear.

For example:

function App({ isLoggedIn }) {
  if (isLoggedIn) {
    return <Dashboard />;
  }

  return <Login />;
}

Here, React renders one of two components.

You can also use a ternary:

function App({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? <Dashboard /> : <Login />}
    </div>
  );
}

Conditional Navigation

A navigation bar may also depend on authentication.

function Navigation({ isLoggedIn }) {
  return (
    <nav>
      <a href="/">Home</a>

      {isLoggedIn ? (
        <>
          <a href="/profile">Profile</a>
          <button>Logout</button>
        </>
      ) : (
        <a href="/login">Login</a>
      )}
    </nav>
  );
}

The navigation changes according to the user’s state.

Conditional Components Based on Role

function App({ role }) {
  if (role === "admin") {
    return <AdminDashboard />;
  }

  if (role === "editor") {
    return <EditorDashboard />;
  }

  return <UserDashboard />;
}

This approach is useful for applications where different users have different capabilities.

Early Return

An early return means returning from a component before reaching the main JSX.

This is particularly useful for loading, error, authentication, and permission states.

For example:

function Profile({ user }) {
  if (!user) {
    return <p>Please log in.</p>;
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

Instead of putting the entire main UI inside another condition, we handle the special case first.

Why Early Returns Are Useful

Compare this:

function Profile({ user }) {
  return (
    <div>
      {user ? (
        <div>
          <h1>{user.name}</h1>
          <p>{user.email}</p>
        </div>
      ) : (
        <p>Please log in.</p>
      )}
    </div>
  );
}

with:

function Profile({ user }) {
  if (!user) {
    return <p>Please log in.</p>;
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

The second version can be easier to read when the component has a larger UI.

Loading UI

Applications often need to retrieve information from an API or another data source.

While the request is running, the application should tell the user that the information is loading.

A common pattern is:

function Products({ loading, products }) {
  if (loading) {
    return <p>Loading products...</p>;
  }

  return (
    <div>
      {products.map((product) => (
        <p key={product.id}>
          {product.name}
        </p>
      ))}
    </div>
  );
}

The component first checks:

if (loading)

If loading is true, it returns the loading UI.

Once loading becomes false, React renders the products.

Loading with State

A simplified example using state:

import { useEffect, useState } from "react";

function Products() {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setProducts([
        { id: 1, name: "Laptop" },
        { id: 2, name: "Keyboard" }
      ]);

      setLoading(false);
    }, 2000);
  }, []);

  if (loading) {
    return <h2>Loading products...</h2>;
  }

  return (
    <div>
      <h1>Products</h1>

      {products.map((product) => (
        <p key={product.id}>
          {product.name}
        </p>
      ))}
    </div>
  );
}

export default Products;

This example simulates a two-second loading period.

In a real application, loading state would normally be controlled by the result of an asynchronous operation.

Error UI

Not every request succeeds.

A network request can fail because:

  • The server is unavailable.
  • The internet connection is interrupted.
  • The API returns an error.
  • The requested resource does not exist.
  • The application encounters an unexpected problem.

A React application should provide useful feedback instead of leaving the user wondering what happened.

For example:

function Products({ loading, error, products }) {
  if (loading) {
    return <p>Loading products...</p>;
  }

  if (error) {
    return <p>Unable to load products.</p>;
  }

  return (
    <div>
      {products.map((product) => (
        <p key={product.id}>
          {product.name}
        </p>
      ))}
    </div>
  );
}

The component now has three states:

Loading
   ↓
Error or Success
   ↓
Display appropriate UI

Loading, Error, and Success

A more complete example:

function Products({ loading, error, products }) {
  if (loading) {
    return <p>Loading products...</p>;
  }

  if (error) {
    return (
      <div>
        <h2>Something went wrong</h2>
        <p>We couldn't load the products.</p>
      </div>
    );
  }

  if (products.length === 0) {
    return <p>No products found.</p>;
  }

  return (
    <div>
      {products.map((product) => (
        <article key={product.id}>
          <h2>{product.name}</h2>
        </article>
      ))}
    </div>
  );
}

This example handles four possible UI states:

  1. Loading
  2. Error
  3. Empty
  4. Success

This is a common pattern in real React applications.

Handling Empty States

An empty state is another form of conditional rendering.

For example:

function ProductList({ products }) {
  if (products.length === 0) {
    return <p>No products are available.</p>;
  }

  return (
    <div>
      {products.map((product) => (
        <p key={product.id}>
          {product.name}
        </p>
      ))}
    </div>
  );
}

Empty states are important because an empty array is not necessarily an error.

For example:

Loading → The application is still retrieving data.

Error → Something went wrong.

Empty → The request succeeded, but there is no data.

Success → Data is available.

These states should usually have different UI.

Conditional Rendering with State

State is frequently used as the condition.

For example:

import { useState } from "react";

function App() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <div>
      <button onClick={() => setIsVisible(!isVisible)}>
        Toggle
      </button>

      {isVisible && (
        <p>
          This content is visible.
        </p>
      )}
    </div>
  );
}

export default App;

The state controls whether the paragraph appears.

When:

isVisible === true

the paragraph is rendered.

When:

isVisible === false

it is not rendered.

Conditional Rendering with Props

Conditions can also come from props.

function Welcome({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome back!</h1>
      ) : (
        <h1>Please log in.</h1>
      )}
    </div>
  );
}

A parent component can control the child’s UI by passing different prop values.

function App() {
  return (
    <Welcome isLoggedIn={true} />
  );
}

This connects conditional rendering with React’s component and props system.

Combining Conditions

You can combine JavaScript conditions using operators such as:

  • &&
  • ||
  • !
  • ===
  • !==
  • >
  • <
  • >=
  • <=

For example:

function Account({ isLoggedIn, isPremium }) {
  return (
    <div>
      {!isLoggedIn && (
        <p>Please log in.</p>
      )}

      {isLoggedIn && isPremium && (
        <p>Premium content unlocked.</p>
      )}
    </div>
  );
}

Here:

!isLoggedIn

means the user is not logged in.

And:

isLoggedIn && isPremium

means both conditions must be true.

Choosing the Right Conditional Rendering Technique

Different situations call for different approaches.

TechniqueBest for
ifComplex conditions
if...elseTwo larger alternatives
Ternary ? :Choosing between two values or UIs
&&Showing something only when true
Early returnLoading, errors, authentication, permissions
Multiple if statementsSeveral mutually exclusive states
Conditional componentSwitching between different components

For example, this is simple and readable:

{isLoggedIn && <Dashboard />}

This is useful when there is only one thing to conditionally show.

For two alternatives:

{isLoggedIn ? <Dashboard /> : <Login />}

For several application states:

if (loading) {
  return <Loading />;
}

if (error) {
  return <Error />;
}

if (products.length === 0) {
  return <EmptyState />;
}

return <ProductList products={products} />;

Avoiding Deeply Nested Ternaries

Although nested ternaries are valid JavaScript, they can become difficult to understand.

For example:

return (
  <div>
    {loading ? (
      <Loading />
    ) : error ? (
      <Error />
    ) : products.length === 0 ? (
      <Empty />
    ) : (
      <ProductList />
    )}
  </div>
);

This works, but as conditions grow, readability suffers.

An early-return approach is often clearer:

if (loading) {
  return <Loading />;
}

if (error) {
  return <Error />;
}

if (products.length === 0) {
  return <Empty />;
}

return <ProductList />;

The important principle is not to avoid ternaries completely. Use them when they make the code clearer.

Conditional Rendering and User Authentication

Authentication is one of the most common real-world examples.

function App({ user }) {
  if (!user) {
    return <Login />;
  }

  return <Dashboard user={user} />;
}

The UI changes depending on whether the user exists.

You can also handle different permissions:

function Dashboard({ user }) {
  if (user.role === "admin") {
    return <AdminDashboard />;
  }

  if (user.role === "editor") {
    return <EditorDashboard />;
  }

  return <UserDashboard />;
}

The same principle can be used for:

  • Admin panels
  • Content management systems
  • SaaS applications
  • E-commerce websites
  • Learning platforms
  • Social media applications

Conditional Rendering and Forms

Conditional rendering is commonly used in forms.

For example:

import { useState } from "react";

function SignupForm() {
  const [submitted, setSubmitted] = useState(false);

  function handleSubmit(event) {
    event.preventDefault();
    setSubmitted(true);
  }

  if (submitted) {
    return <h2>Account created successfully!</h2>;
  }

  return (
    <form onSubmit={handleSubmit}>
      <input placeholder="Name" />
      <input placeholder="Email" />

      <button type="submit">
        Create Account
      </button>
    </form>
  );
}

export default SignupForm;

Before submission, the form is shown.

After submission, the success message is shown.

Conditional Rendering and Search Results

Search interfaces frequently have several states.

function SearchResults({ loading, results, error }) {
  if (loading) {
    return <p>Searching...</p>;
  }

  if (error) {
    return <p>Search failed.</p>;
  }

  if (results.length === 0) {
    return <p>No results found.</p>;
  }

  return (
    <div>
      {results.map((result) => (
        <article key={result.id}>
          <h2>{result.title}</h2>
        </article>
      ))}
    </div>
  );
}

This gives users useful feedback regardless of the current application state.

Real-World Web4Learners Example

Imagine Web4Learners has a React tutorial search page.

The page might have these states:

Before Searching

Search React tutorials

While Searching

Searching for React...

Results Found

React Props
React State
React Events
React Hooks

No Results

No tutorials found.

Error

Unable to load tutorials. Please try again.

A component could represent these states using conditional rendering:

function TutorialResults({
  loading,
  error,
  tutorials
}) {
  if (loading) {
    return (
      <p>
        Searching for tutorials...
      </p>
    );
  }

  if (error) {
    return (
      <div>
        <h2>Unable to load tutorials</h2>
        <button>Try Again</button>
      </div>
    );
  }

  if (tutorials.length === 0) {
    return (
      <p>
        No tutorials found.
      </p>
    );
  }

  return (
    <div>
      {tutorials.map((tutorial) => (
        <article key={tutorial.id}>
          <h2>{tutorial.title}</h2>
          <p>{tutorial.description}</p>
        </article>
      ))}
    </div>
  );
}

export default TutorialResults;

This is a realistic example of how conditional rendering controls the interface of a content-based website.

Image Placement: Conditional Rendering Flow

Place this image immediately after the “How Conditional Rendering Works in React” section.

Create a modern 16:9 educational infographic showing:

Condition → True / False → Different UI

Use three examples:

  • Logged in → Dashboard
  • Logged out → Login
  • Loading → Loading UI

Use a modern Web4Learners design style with clean typography, rounded cards, subtle gradients, React-inspired developer visuals, and minimal text. Make the flow immediately understandable to a beginner.

Image Placement: React UI States

Place this image immediately before the “Loading UI” section.

Create a modern 16:9 infographic showing four common React UI states:

Loading → Success → Empty → Error

Represent each state with a simple modern interface card.

Use a clean developer-focused design with contemporary typography, rounded corners, subtle gradients, and minimal text. Avoid making the image look like an old-fashioned flowchart.

Common Conditional Rendering Mistakes

Using = Instead of ===

Incorrect:

if (isLoggedIn = true) {
  return <Dashboard />;
}

This assigns a value instead of checking it.

Usually you should simply write:

if (isLoggedIn) {
  return <Dashboard />;
}

Or when comparing values:

if (role === "admin") {
  return <AdminDashboard />;
}

Using && with a Number Without Checking It

Potentially problematic:

{count && <p>There are items.</p>}

If count is 0, React can render 0.

Prefer:

{count > 0 && (
  <p>There are items.</p>
)}

Making Ternaries Too Complicated

Avoid turning a simple condition into a large nested expression.

Instead of:

condition1
  ? ...
  : condition2
  ? ...
  : condition3
  ? ...
  : ...

consider early returns or separate components.

Forgetting the Empty State

An application should not assume that data always exists.

For example:

if (products.length === 0) {
  return <p>No products found.</p>;
}

An empty result can be a valid application state.

Treating Errors as Loading

Loading and error states are different.

Avoid showing:

Loading...

forever when a request has actually failed.

Represent the states separately:

if (loading) {
  return <Loading />;
}

if (error) {
  return <Error />;
}

Best Practices for Conditional Rendering

Keep Conditions Easy to Understand

Simple conditions are easier to maintain.

Instead of repeating complicated logic:

{user && user.account && user.account.subscription && ...}

consider calculating a meaningful value first when appropriate.

const hasPremiumAccess =
  user?.account?.subscription === "premium";

Then:

{hasPremiumAccess && <PremiumContent />}

Use Early Returns for Major States

Early returns are particularly useful for:

  • Loading
  • Error
  • Authentication
  • Authorization
  • Empty data

Example:

if (loading) {
  return <Loading />;
}

if (error) {
  return <Error />;
}

Use Ternaries for Simple Alternatives

Good:

{isLoggedIn ? <Dashboard /> : <Login />}

This clearly expresses two alternatives.

Use && for Optional Content

Good:

{isAdmin && <AdminTools />}

The intent is immediately understandable.

Create Separate Components When UI Gets Large

If a conditional block becomes large, move it into its own component.

Instead of keeping a huge conditional inside one component:

{isAdmin ? (
  // lots of JSX
) : (
  // lots more JSX
)}

consider:

{isAdmin ? <AdminPanel /> : <UserPanel />}

This keeps the parent component easier to understand.

Conditional Rendering Cheat Sheet

SituationRecommended approach
One condition&&
Two alternativesTernary
Complex logicif
Loading stateEarly return
Error stateEarly return
Empty stateEarly return or conditional rendering
Different user rolesif or conditional components
Show/hide UI&&
Switch between componentsTernary or if
Multiple mutually exclusive statesMultiple if statements

Basic if

if (isLoggedIn) {
  return <Dashboard />;
}

return <Login />;

Ternary

{isLoggedIn ? <Dashboard /> : <Login />}

Logical &&

{isAdmin && <AdminTools />}

Early Return

if (loading) {
  return <Loading />;
}

Multiple States

if (loading) {
  return <Loading />;
}

if (error) {
  return <Error />;
}

if (items.length === 0) {
  return <Empty />;
}

return <List items={items} />;

Practice Exercise

Build a React Product Dashboard that handles different UI states.

Your application should have:

  • A loading state
  • An error state
  • An empty state
  • A successful product list
  • An admin-only button
  • A login/logout state

Try to use:

if
? :
&&

and early returns.

Expected Behavior

When data is loading:

Loading products...

When an error occurs:

Unable to load products.

When there are no products:

No products found.

When products are available:

Laptop
Keyboard
Mouse

If the user is an administrator, also show:

Manage Products

If the user is not logged in, show:

Please log in.

Try to organize the conditions so that the component remains easy to read.

Key Takeaways

Conditional rendering allows React applications to display different UI based on application state, props, data, and user actions.

The most important concepts to remember are:

  • Conditional rendering means showing different UI depending on a condition.
  • React uses normal JavaScript conditions for conditional rendering.
  • if statements are useful for complex conditions.
  • The ternary operator is useful when choosing between two alternatives.
  • Logical && is useful when something should appear only when a condition is true.
  • Be careful when using && with numbers such as 0.
  • Multiple if statements can handle several mutually exclusive states.
  • Early returns make loading, error, authentication, and empty states easier to manage.
  • Conditional components can switch between completely different UI sections.
  • Loading, error, empty, and success states should usually be handled separately.
  • Conditions can be based on state, props, API data, authentication, permissions, and user actions.
  • Avoid deeply nested ternary expressions when they make the code difficult to read.
  • Move large conditional UI sections into separate components when appropriate.
  • Good conditional rendering makes an application’s interface predictable and easier for users to understand.

A useful way to think about conditional rendering is:

Application State
       ↓
Condition
       ↓
Choose UI
       ↓
React Renders It

Once you understand this pattern, you can build interfaces that respond naturally to changing data and user actions. Conditional rendering is one of the core techniques that turns static React components into dynamic application interfaces.

Leave a Comment