Conditional Rendering in React: The Ultimate Guide



This content originally appeared on DEV Community and was authored by Shefali

Conditional rendering in React allows you to display different UI elements based on conditions. This is useful for handling authentication states, user permissions, loading states, and more.

Just like JavaScript provides if-else, ternary (? :), logical AND (&&), and switch-case, React also uses these methods for rendering components conditionally.

In this post, you’ll learn about all these techniques, their best use cases, and best practices.

Before we get started, don’t forget to subscribe to my newsletter!
Get the latest tips, tools, and resources to level up your web development skills delivered straight to your inbox. Subscribe here!

Now let’s jump right into it!🚀

What is Conditional Rendering?

Conditional rendering means changing the UI based on a condition.

For example, if a user is logged in, display a welcome message; otherwise, show a login prompt.

function UserGreeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h2>Welcome, User!</h2>;
  } else {
    return <h2>Please Login!</h2>;
  }
}

Why is Conditional Rendering Important?

In React apps, the UI needs to change based on different situations, like user actions or data availability. Conditional rendering helps show or hide elements based on these conditions, making the app more interactive and user-friendly.

Here are some common examples:

  • Authentication – Show login/signup for guests and a dashboard for logged-in users.
  • Loading States – Display a loading spinner while fetching data.
  • User Roles – Show different content for admins, editors, or guests.
  • Error Handling – Show error messages when something goes wrong.
  • Feature Toggles – Enable or disable features dynamically.

You can write cleaner and readable code by using the right conditional rendering technique and also enhance the user experience.

Techniques for Conditional Rendering in React

Different ways to render UI dynamically based on conditions:

Conditional Rendering Using if-else

This is the simplest and most readable method.

function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h2>Welcome, User!</h2>;
  } else {
    return <h2>Please Login!</h2>;
  }
}

Here, if the isLoggedIn is true, then the “Welcome, User!” will show; otherwise, “Please Login” will show.

Best Use Case: When conditions are complex and require multiple checks.

For example:

function UserAccess({ role }) {
  if (role === "admin") {
    return <h2>Welcome, Admin!</h2>;
  } else if (role === "editor") {
    return <h2>Welcome, Editor!</h2>;
  } else {
    return <h2>Welcome, Guest!</h2>;
  }
}

Ternary Operator (? :) for Conditional Rendering

If you want to check a simple condition, then the ternary operator is the best.

For example:

function UserStatus({ isLoggedIn }) {
  return (
    <h2>{isLoggedIn ? "Welcome, User!" : "Please Login!"}</h2>
  );
}

Here, if the isLoggedIn is true, then “Welcome, User!” otherwise “Please Login” will be rendered.

Best Use Case: When conditions are short and can be written in a single line.

Conditional Rendering with Logical AND (&&)

When you only need to render content if a certain condition is true, then the use of && operator is best.

For example:

function ShowMessage({ hasMessages }) {
  return (
    <div>
      <h2>Welcome!</h2>
      {hasMessages && <p>You have new messages.</p>}
    </div>
  );
}

Here, if hasMessages is true, then it will render “You have new messages.” Otherwise, nothing will be shown.

Best Use Case: When you want to display content based on only one condition being true.

Switch-Case for Multiple Conditions

If you want to handle more than one case, then it’s better to use switch-case.

For example:

function StatusMessage({ status }) {
  switch (status) {
    case "loading":
      return <h2>Loading...</h2>;
    case "error":
      return <h2>Error Occurred!</h2>;
    case "success":
      return <h2>Data Loaded Successfully!</h2>;
    default:
      return <h2>Unknown Status</h2>;
  }
}

Best Use Case: When you want to check multiple conditions.

Component-Based Conditional Rendering

If the UI is more complex, then it’s better to break it into components.

For example:

function Welcome() {
  return <h2>Welcome, User!</h2>;
}

function PleaseLogin() {
  return <h2>Please Login!</h2>;
}

function App({ isLoggedIn }) {
  return isLoggedIn ? <Welcome /> : <PleaseLogin />;
}

Here, this will render the Welcome component if the isLoggedIn is true; otherwise, it will render the PleaseLogin component.

Best Use Case: When working with complex UIs.

Conditional Rendering in Lists

Using conditions inside .map() for dynamic lists:

function TaskList({ tasks }) {
  return (
    <ul>
      {tasks.length > 0 ? (
        tasks.map((task, index) => <li key={index}>{task}</li>)
      ) : (
        <p>No tasks available.</p>
      )}
    </ul>
  );
}

Here, if the tasks.length > 0, then the list will be shown; otherwise, “No tasks available” will render.

Best Use Case: Rendering specific items in a list based on conditions.

Using useState for Dynamic UI

When you want to change the UI based on user interaction, then you can use the useState.

Example: Changing the UI on Button Click

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

  return (
    <div>
      <button onClick={() => setIsVisible(!isVisible)}>
        Toggle Message
      </button>
      {isVisible && <p>Hello, this is a toggled message!</p>}
    </div>
  );
}

Here, the message will show and hide on button click.

Best Use Case: Making the UI dynamic.

Optional Chaining (?.) for Safe Rendering

When you want to handle nested object properties safely, you can use optional chaining.

For example:

function UserProfile({ user }) {
  return <h2>{user?.name ? `Hello, ${user.name}` : "Guest"}</h2>;
}

Here, user?.name checks if the user object exists and has a name property.

If user.name exists, then it will display “Hello, [User’s Name]”. If user is undefined or null, then it won’t throw an error because of optional chaining (?.). And if user.name is missing, “Guest” will be shown.

Best Use Case: Avoids errors when dealing with undefined or null values.

Conditional Styling (CSS & Tailwind)

You can change the elements’ styles with conditional rendering.

For example:

function Button({ isActive }) {
  return <button className={isActive ? "bg-blue-500" : "bg-gray-500"}>Click Me</button>;
}

Here, if the isActive is true, then the background color of the button will be blue, otherwise, it will be gray.

Best Use Case: Changing styles dynamically.

Lazy Loading Components for Performance

Use React.lazy() to conditionally render components only when needed.

For example:

const Profile = React.lazy(() => import("./Profile"));
function App({ isLoggedIn }) {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      {isLoggedIn ? <Profile /> : <p>Please log in</p>}
    </Suspense>
  );
}

Here,

If User is Logged In (isLoggedIn = true):

  • React tries to load the Profile component.
  • While loading, “Loading…” is displayed.
  • And after loading, the Profile appears.

If User is Not Logged In (isLoggedIn = false):

  • “Please log in” is shown immediately (Profile is not loaded).

Best Use Case: Optimize performance by loading components only when required.

Returning JSX from Functions for Cleaner Code

If the same conditional rendering is repeated, then it’s better to extract it into a separate function.

For example:

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

function App({ isLoggedIn }) {
  return <div>{getButton(isLoggedIn)}</div>;
}

Here,

  • The function getButton(isLoggedIn) returns either a Logout or Login button based on the isLoggedIn value.
  • The getButton(isLoggedIn) function is called inside JSX in the App component.

Best Use Case: Keeping code DRY (Don’t Repeat Yourself).

Best Practices for Conditional Rendering

  • Use && or Ternary (? : ) for simple conditions.
  • Use if-else or switch-case for complex conditions.
  • Use functions or separate components for maintainability.
  • Return null if you don’t want to render anything. Example:
function EmptyComponent({ shouldRender }) {
  return shouldRender ? <h2>Rendered</h2> : null;
}

Here, if the shouldRender is false, then it will return null, and nothing will be rendered.

🎯Wrapping Up

That’s all for today!

For paid collaboration connect with me at : connect@shefali.dev

I hope this list helps you. 🚀

If you found this post helpful, here’s how you can support my work:
☕ Buy me a coffee – Every little contribution keeps me motivated!
📩 Subscribe to my newsletter – Get the latest tech tips, tools & resources.
𝕏 Follow me on X (Twitter) – I share daily web development tips & insights.

Keep coding & happy learning!


This content originally appeared on DEV Community and was authored by Shefali