Conditional Rendering
React lets you render different content based on conditions - showing a login button to guests, a dashboard to users, or loading spinners while data loads.
Using if Statements
For complete conditional blocks, use regular if statements:
function Greeting({ isLoggedIn }) {
if (isLoggedIn) {
return <h1>Welcome back!</h1>;
}
return <h1>Please sign in.</h1>;
}
Ternary Operator
For inline conditions, use the ternary operator condition ? true : false:
function Greeting({ isLoggedIn }) {
return (
<h1>
{isLoggedIn ? 'Welcome back!' : 'Please sign in.'}
</h1>
);
}
Rendering Different Components
function Dashboard({ user }) {
return (
<div>
{user ? (
<UserDashboard user={user} />
) : (
<LoginPrompt />
)}
</div>
);
}
Logical AND (&&)
For "show this or nothing" cases:
function Notifications({ messages }) {
return (
<div>
{messages.length > 0 && (
<span className="badge">{messages.length}</span>
)}
</div>
);
}
Watch Out for Zero!
// ❌ Bug: renders "0" when count is 0
{count && <p>You have {count} items</p>}
// ✅ Fixed: explicitly check the condition
{count > 0 && <p>You have {count} items</p>}
Conditional CSS Classes
function Button({ isPrimary, isDisabled }) {
return (
<button
className={`btn ${isPrimary ? 'btn-primary' : 'btn-secondary'} ${
isDisabled ? 'btn-disabled' : ''
}`}
disabled={isDisabled}
>
Click me
</button>
);
}
Using Template Literals
<div className={`card ${isActive ? 'card-active' : ''}`}>
Content
</div>
Multiple Conditions
Nested Ternaries (Use Sparingly)
function Status({ status }) {
return (
<span>
{status === 'loading' ? 'Loading...' :
status === 'error' ? 'Error!' :
status === 'success' ? 'Done!' :
'Unknown'}
</span>
);
}
Better: Early Returns
function Status({ status }) {
if (status === 'loading') return <Spinner />;
if (status === 'error') return <Error />;
if (status === 'success') return <Success />;
return null;
}
Object Lookup
function Status({ status }) {
const statusComponents = {
loading: <Spinner />,
error: <ErrorMessage />,
success: <SuccessMessage />,
};
return statusComponents[status] || <DefaultMessage />;
}
Common Patterns
Loading States
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
// ... fetch user data
if (loading) {
return <Spinner />;
}
return <Profile user={user} />;
}
Error States
function DataDisplay({ data, error, loading }) {
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
if (!data) return <EmptyState />;
return <DataTable data={data} />;
}
Authentication
function App() {
const [user, setUser] = useState(null);
return (
<div>
<Header />
{user ? (
<Dashboard user={user} onLogout={() => setUser(null)} />
) : (
<LoginPage onLogin={setUser} />
)}
<Footer />
</div>
);
}
Feature Flags
function App({ features }) {
return (
<div>
<MainContent />
{features.showNewFeature && <NewFeature />}
{features.enableBetaMode && <BetaBanner />}
</div>
);
}
Preventing Render
Return null to render nothing:
function WarningBanner({ warning }) {
if (!warning) {
return null; // Renders nothing
}
return <div className="warning">{warning}</div>;
}
Conditional Attributes
function Input({ isRequired, isDisabled }) {
return (
<input
type="text"
required={isRequired}
disabled={isDisabled}
// Only add aria-invalid if there's an error
{...(hasError && { 'aria-invalid': true })}
/>
);
}
Key Takeaways
- Use
ifstatements for complete conditional blocks - Use ternary
? :for choosing between two options - Use
&&for "show or nothing" cases - Watch out for falsy values like
0with&& - Return
nullto render nothing - For multiple conditions, consider early returns or object lookup
- Keep conditionals simple and readable