Skip to main content

Command Palette

Search for a command to run...

Conditional Rendering in React โ€“ Showing Dynamic UI

Updated
โ€ข11 min readโ€ขView as Markdown

A real application rarely shows exactly the same UI all the time.

Think about a social media application.

If you're logged in:

Welcome back, Saurabh ๐Ÿ‘‹

[ Profile ] [ Logout ]

If you're logged out:

Welcome!

[ Login ] [ Sign Up ]

The application is making a decision about what to display.

This is called Conditional Rendering.

Today we'll learn how React uses JavaScript conditions to dynamically decide what should appear on the screen.


๐Ÿง  What Is Conditional Rendering?

Conditional rendering means:

Rendering different UI depending on whether a condition is true or false.

For example:

function App() {
  const isLoggedIn = true;

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

If:

isLoggedIn === true

React renders:

Welcome!

Otherwise:

Please Login

โš›๏ธ Why Is Conditional Rendering Important?

Conditional rendering is everywhere in modern applications.

For example:

Authentication

Logged in โ†’ Dashboard
Logged out โ†’ Login

Loading

Loading โ†’ Spinner
Loaded โ†’ Content

Errors

Error โ†’ Error message
No error โ†’ Data

Permissions

Admin โ†’ Admin Panel
User โ†’ User Dashboard

Empty states

Cart has products โ†’ Cart items
Cart is empty โ†’ "Your cart is empty"

Conditional rendering allows one component to adapt to different situations.


๐Ÿ”€ Using the Ternary Operator

One of the most common ways to conditionally render UI is the ternary operator.

Syntax:

condition ? valueIfTrue : valueIfFalse

Example:

const isLoggedIn = true;

return (
  <h1>
    {isLoggedIn ? "Welcome Back!" : "Please Login"}
  </h1>
);

The condition:

isLoggedIn

is checked.

If it's true:

Welcome Back!

If it's false:

Please Login

๐Ÿงฉ Conditional Components

We can use the ternary operator to render entire components.

function App() {
  const isLoggedIn = true;

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

This is much more powerful than simply changing text.

The UI itself changes.


๐Ÿ‘ค Example: Login / Logout

Let's create a simple authentication UI.

import { useState } from "react";

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <div>
      {isLoggedIn ? (
        <>
          <h1>Welcome Back! ๐Ÿ‘‹</h1>

          <button onClick={() => setIsLoggedIn(false)}>
            Logout
          </button>
        </>
      ) : (
        <>
          <h1>Please Login</h1>

          <button onClick={() => setIsLoggedIn(true)}>
            Login
          </button>
        </>
      )}
    </div>
  );
}

export default App;

Now our UI changes based on state.

The flow is:

User clicks Login
       โ†“
setIsLoggedIn(true)
       โ†“
State changes
       โ†“
Component re-renders
       โ†“
Dashboard UI appears

This connects everything we've learned so far:

State + Events + Conditional Rendering


โšก Logical AND &&

Sometimes we don't need an else.

We only want to display something when a condition is true.

For example:

const isAdmin = true;

return (
  <div>
    {isAdmin && <button>Admin Panel</button>}
  </div>
);

If:

isAdmin === true

the button appears.

If:

isAdmin === false

nothing is rendered.


๐Ÿง  Understanding &&

The JavaScript expression:

true && "Hello"

returns:

Hello

But:

false && "Hello"

returns:

false

React doesn't render the boolean false as visible UI.

That's why this works:

{isLoggedIn && <Dashboard />}

โš ๏ธ Be Careful With 0 &&

There's an important JavaScript gotcha.

Consider:

const count = 0;

return (
  <div>
    {count && <p>Items available</p>}
  </div>
);

You might expect nothing.

But count is:

0

and React can render that 0.

You may end up seeing:

0

A safer condition can be:

{count > 0 && <p>Items available</p>}

This is an important detail when working with numeric values.


๐Ÿ”„ Using if Statements

Not every condition should be written inside JSX.

Sometimes a normal if statement is cleaner.

For example:

function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h1>Welcome Back!</h1>;
  }

  return <h1>Please Login</h1>;
}

This is very readable.


๐Ÿง  Early Return

We can use an early return to handle a specific condition.

function Dashboard({ isLoggedIn }) {
  if (!isLoggedIn) {
    return <h2>Please login first.</h2>;
  }

  return <h1>Dashboard</h1>;
}

The logic becomes:

Not logged in?
      โ†“
Show login message
      โ†“
Stop

Logged in?
      โ†“
Show dashboard

Early returns are particularly useful when a component has multiple states.


โณ Loading States

Conditional rendering is extremely useful when fetching data.

For example:

function UserProfile({ loading }) {
  if (loading) {
    return <p>Loading...</p>;
  }

  return <h1>User Profile</h1>;
}

The UI can have different states:

Loading
   โ†“
Success
   โ†“
Display Data

Or:

Loading
   โ†“
Error

We'll use this heavily when we start working with APIs.


โŒ Error States

Suppose:

function UserData({ error }) {
  if (error) {
    return <p>Something went wrong. โŒ</p>;
  }

  return <p>User loaded successfully! โœ…</p>;
}

Now our UI responds to errors.

A mature application usually has at least these states:

Loading
Success
Error
Empty

Thinking in terms of these states is extremely useful when building real applications.


๐Ÿ“ญ Empty States

Suppose we have a list:

const tasks = [];

We can display:

{tasks.length === 0 ? (
  <p>No tasks available.</p>
) : (
  <TaskList tasks={tasks} />
)}

If the array is empty:

No tasks available.

Otherwise:

Task List

This is called an empty state.


๐Ÿ”ข Conditional Rendering Based on Numbers

We can use normal comparisons.

const age = 23;

return (
  <div>
    {age >= 18 ? (
      <p>You are an adult.</p>
    ) : (
      <p>You are a minor.</p>
    )}
  </div>
);

JavaScript conditions work naturally inside React.

For example:

age > 18
age === 18
age !== 18
items.length > 0

๐ŸŽจ Dynamic Styling With Conditions

Conditional rendering isn't limited to elements.

We can also change classes.

function Button({ active }) {
  return (
    <button className={active ? "active" : "inactive"}>
      Button
    </button>
  );
}

If:

active === true

the class becomes:

active

Otherwise:

inactive

This is useful for:

  • Active navigation links

  • Selected buttons

  • Tabs

  • Dark mode

  • Validation states


๐ŸŒ™ Example: Dark Mode

Let's combine State + Events + Conditional UI.

import { useState } from "react";

function App() {
  const [darkMode, setDarkMode] = useState(false);

  return (
    <div className={darkMode ? "dark" : "light"}>
      <h1>
        {darkMode ? "Dark Mode ๐ŸŒ™" : "Light Mode โ˜€๏ธ"}
      </h1>

      <button onClick={() => setDarkMode(prev => !prev)}>
        Toggle Theme
      </button>
    </div>
  );
}

export default App;

The state:

darkMode

controls the UI.

The event:

onClick

changes the state.

The conditional:

darkMode ? "dark" : "light"

changes the appearance.


๐Ÿงฉ Multiple Conditions

Sometimes there are more than two possible states.

For example:

Admin
User
Guest

We could use:

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

  if (role === "user") {
    return <UserDashboard />;
  }

  return <GuestDashboard />;
}

This is often easier to read than deeply nested ternaries.


โš ๏ธ Avoid Nested Ternaries

This works:

condition
  ? <A />
  : otherCondition
    ? <B />
    : <C />

But once conditions become complex, readability suffers.

Prefer:

if (condition) {
  return <A />;
}

if (otherCondition) {
  return <B />;
}

return <C />;

Simple code is usually easier to maintain.


๐Ÿง  Conditional Rendering With Functions

We can move complicated logic outside JSX.

function getMessage(isLoggedIn, isAdmin) {
  if (!isLoggedIn) {
    return "Please login";
  }

  if (isAdmin) {
    return "Welcome Admin";
  }

  return "Welcome User";
}

Then:

<h1>{getMessage(isLoggedIn, isAdmin)}</h1>

This keeps JSX cleaner.


๐Ÿ”ฅ Real-World Example: Product Availability

Imagine an e-commerce product.

function Product({ stock }) {
  return (
    <div>
      <h2>Mechanical Keyboard</h2>

      {stock > 0 ? (
        <button>Add to Cart</button>
      ) : (
        <p>Out of Stock โŒ</p>
      )}
    </div>
  );
}

Now:

stock = 10

shows:

[ Add to Cart ]

while:

stock = 0

shows:

Out of Stock โŒ

This is exactly how real applications make decisions based on data.


๐Ÿ”„ Combining State, Events & Conditions

Let's build a small notification example.

import { useState } from "react";

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

  return (
    <div>
      <button
        onClick={() => setShowMessage(prev => !prev)}
      >
        {showMessage ? "Hide Message" : "Show Message"}
      </button>

      {showMessage && (
        <p>Hello! This message is visible. ๐Ÿ‘‹</p>
      )}
    </div>
  );
}

Here:

State

showMessage

Event

onClick

Conditional rendering

showMessage && <p>...</p>

Dynamic button text

showMessage
  ? "Hide Message"
  : "Show Message"

This is the kind of pattern you'll use constantly in React.


๐Ÿง  React Doesn't Have Its Own Conditional Syntax

One thing I found important today:

React doesn't create a completely new programming language for conditions.

We're still using JavaScript.

We use:

if
else
?
:
&&
!
=== 
>
<

inside React components.

For example:

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

The JSX simply allows JavaScript expressions to control what gets rendered.


๐Ÿ† Best Practices

1. Keep conditions readable

Prefer:

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

over unnecessarily complicated expressions.


2. Use && when there is only a true case

{isAdmin && <AdminPanel />}

3. Use if for complex logic

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

4. Avoid deeply nested ternaries

They become difficult to understand.


5. Think in UI states

When designing a component, ask:

What does the user see when:
- Loading?
- Successful?
- Empty?
- Error?
- Logged out?

This mindset helps create better applications.


6. Keep JSX clean

Move complicated calculations or decisions into variables/functions when necessary.

For example:

const message = isLoggedIn
  ? "Welcome Back!"
  : "Please Login";

Then:

<h1>{message}</h1>

๐Ÿš€ Complete Example: User Dashboard

Let's combine today's concepts.

import { useState } from "react";

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [isAdmin, setIsAdmin] = useState(false);

  if (!isLoggedIn) {
    return (
      <div>
        <h1>Welcome ๐Ÿ‘‹</h1>

        <button onClick={() => setIsLoggedIn(true)}>
          Login
        </button>
      </div>
    );
  }

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

      {isAdmin && (
        <button>
          Admin Panel
        </button>
      )}

      <button onClick={() => setIsLoggedIn(false)}>
        Logout
      </button>
    </div>
  );
}

export default App;

This small example already demonstrates:

  • State

  • Events

  • if

  • &&

  • Conditional components

  • Login/logout

  • Role-based UI


๐Ÿ’ก My Biggest Takeaway

Today's biggest takeaway is:

React UI is a function of state and data.

When state changes, the conditions may change.

When the conditions change, the UI can change.

For example:

isLoggedIn = false
        โ†“
<Login />

Then:

isLoggedIn = true
        โ†“
<Dashboard />

This is one of the most important mental models for React.

Instead of manually telling the browser:

"Hide this element."

We describe:

"If this condition is true, this is what the UI should look like."

React handles the rendering.


๐Ÿš€ Final Summary

Today I learned:

  • What conditional rendering is

  • Ternary operator

  • && conditional rendering

  • if statements

  • Early returns

  • Loading states

  • Error states

  • Empty states

  • Conditional styling

  • Multiple conditions

  • Dynamic UI

  • State + Events + Conditions

  • Why nested ternaries can be problematic

  • How JavaScript controls JSX

The progression is becoming clearer:

Day 62
Props
 โ†“
Day 63
State
 โ†“
Day 64
Events
 โ†“
Day 65
Conditional Rendering
 โ†“
Interactive React UI

100 Days of Code: My Journey to Becoming a Full Stack Developer

Part 1 of 50

Welcome to my 100 Days of Code journey! In this series, I'll document my daily progress as I learn Full Stack Web Development from the ground up. Every post will cover what I learned, challenges I faced, mistakes I made, and the projects I built. My goal is not just to complete 100 days but to become a better developer through consistency, discipline, and learning in public. Topics I'll cover include: โ€ข Git & GitHub โ€ข HTML, CSS & JavaScript โ€ข React.js โ€ข Node.js & Express โ€ข MongoDB โ€ข APIs โ€ข Real-world Projects โ€ข AI tools for Developers Whether you're just starting out or revising your fundamentals, I hope this journey helps you learn alongside me. Let's build, learn, and grow together! ๐Ÿš€

More from this blog

T

TheSaurceCode

73 posts

Documenting my journey to becoming a Full Stack Developer through daily blogs, coding challenges, projects, tutorials, and lessons learned. Learn, build, and grow with me