Conditional Rendering
Conditional rendering means showing different UI for different state or props.
In React, you use normal JavaScript to decide what JSX to return.
Early Returns
Early returns are clear when a component has distinct states.
function UserPanel({ user, isLoading, error }) {
if (isLoading) {
return <p>Loading user...</p>;
}
if (error) {
return <p role="alert">Could not load user.</p>;
}
if (!user) {
return <p>No user selected.</p>;
}
return <h2>{user.name}</h2>;
}This avoids deeply nested JSX.
Ternary Expressions
Use a ternary when you need one of two branches inside JSX.
function LoginStatus({ isLoggedIn }) {
return (
<p>
{isLoggedIn ? "You are signed in." : "Please sign in."}
</p>
);
}Ternaries are best when both branches are short.
If the JSX becomes hard to scan, move the logic into variables or early returns.
function AccountAction({ isLoggedIn, isSaving }) {
let action;
if (isSaving) {
action = <button disabled>Saving...</button>;
} else if (isLoggedIn) {
action = <button>Sign out</button>;
} else {
action = <button>Sign in</button>;
}
return <div className="account-action">{action}</div>;
}Logical AND
Use && to render something only when a condition is true.
function AlertBanner({ message }) {
return (
<header>
<h1>Dashboard</h1>
{message && <p role="alert">{message}</p>}
</header>
);
}Be careful with numbers.
// Bug: renders 0 when count is 0
{count && <p>{count} unread messages</p>}
// Better
{count > 0 && <p>{count} unread messages</p>}React renders 0, but ignores false, null, and undefined.
Returning null
A component can return null to render nothing.
function AdminTools({ user }) {
if (user.role !== "admin") {
return null;
}
return <button>Open admin tools</button>;
}This is useful for small optional components.
Do not overuse it for major application flow. For larger cases, rendering an explicit empty state is often clearer.
Conditional Classes and Attributes
Conditional rendering is not only about whole elements. Props can be conditional too.
function TabButton({ isSelected, children }) {
return (
<button
className={isSelected ? "tab selected" : "tab"}
aria-selected={isSelected}
>
{children}
</button>
);
}This keeps the same button in the DOM while changing how it behaves and appears.
Preserving or Resetting State
Switching between different component types can reset state.
{mode === "view" ? <ProfileView /> : <ProfileEditor />}If both branches are the same component type in the same position, React preserves state.
<ProfileEditor mode={mode} />Sometimes preservation is good. Sometimes you want a reset. Use keys intentionally when identity changes.
<ProfileEditor key={user.id} user={user} />Common Mistakes
- Nesting several ternaries until JSX becomes unreadable.
- Using
count && ...and rendering0. - Returning nothing from a component instead of
null. - Hiding important empty states by rendering a blank screen.
- Accidentally resetting state by switching component types.
What is a common problem with {items.length && <List />}?
Practice Challenge
Build a DataView component with these props:
isLoadingerroritems
Requirements:
- show a loading message first
- show an error message if there is an error
- show an empty state when
itemsis empty - otherwise render the item names in a list with stable keys
Use early returns for the main branches.
Recap
Conditional rendering uses regular JavaScript. Choose early returns, ternaries, &&, null, conditional props, and keys based on the shape of the UI state you need to represent.