Conditional Rendering
Conditional rendering in React: use if, early returns, ternaries, &&, ||, ??, null, and UI states like loading, error, empty, and success.
Conditional Rendering
Conditional Rendering is the technique of displaying different UI based on a condition.
In React, you use normal JavaScript conditions to decide what should appear in the UI.
function Greeting({ isLoggedIn }: { isLoggedIn: boolean }) {if (isLoggedIn) {return <h1>Welcome back!</h1>;}return <h1>Please log in.</h1>;}
If isLoggedIn is true:
Welcome back!
If it is false:
Please log in.
The fundamental idea is:
Condition↓Choose UI↓React renders the result
Learning Objectives
By the end of this lesson, you will understand:
- What conditional rendering is
- Using
ifstatements and early returns - Ternary operators
- Logical
&&,||, and?? - Rendering nothing with
null - Conditional attributes, text, and classes
- Loading, error, empty, and success states
- Common mistakes and best practices
- Interview questions for conditional rendering
1. What Is Conditional Rendering?
A React component doesn't always need to render the same UI.
User logged in?│┌───┴───┐Yes No│ │▼ ▼Dashboard Login
React allows you to express this directly in JavaScript.
2. The Simplest Example
function UserStatus({ isLoggedIn }: { isLoggedIn: boolean }) {if (isLoggedIn) {return <p>Welcome!</p>;}return <p>Please log in.</p>;}<UserStatus isLoggedIn={true} /> // Welcome!<UserStatus isLoggedIn={false} /> // Please log in.
3. Conditional Rendering with if
The normal JavaScript if statement works well when UI branches are substantially different.
function Dashboard({ isAdmin }: { isAdmin: boolean }) {if (isAdmin) {return <AdminDashboard />;}return <UserDashboard />;}
This is often clearer than forcing everything into JSX.
4. Early Returns
A very common React pattern is the early return.
function Profile({ user }: { user: { name: string; email: string } | null }) {if (!user) {return <p>Please log in.</p>;}return (<div><h1>{user.name}</h1><p>{user.email}</p></div>);}
user exists?│┌───┴───┐No Yes│ │▼ ▼Login Profile
Early returns make components easier to read.
5. Multiple Conditions with if
function Dashboard({ role }: { role: string }) {if (role === "admin") {return <AdminDashboard />;}if (role === "manager") {return <ManagerDashboard />;}if (role === "user") {return <UserDashboard />;}return <NotFound />;}
This is often clearer than deeply nested ternary expressions.
6. Ternary Operator
For simple conditions, use the JavaScript ternary operator:
condition? valueIfTrue: valueIfFalse
function Greeting({ isLoggedIn }: { isLoggedIn: boolean }) {return (<h1>{isLoggedIn ? "Welcome back!" : "Please log in"}</h1>);}
7. Ternary with Components
function App({ isLoggedIn }: { isLoggedIn: boolean }) {return (<>{isLoggedIn ? <Dashboard /> : <Login />}</>);}
This is very common in React.
8. Ternary with JSX Blocks
function Account({ isLoggedIn }: { isLoggedIn: boolean }) {return (<section>{isLoggedIn ? (<div><h1>My Account</h1><p>Welcome back.</p><button>Logout</button></div>) : (<div><h1>Guest</h1><p>Please log in.</p><button>Login</button></div>)}</section>);}
9. When Should You Use if vs Ternary?
Use if when:
- Branches are large
- There are multiple conditions
- You want early returns
- The logic is easier to read outside JSX
Use a ternary when:
- There are two simple alternatives
- The condition belongs naturally inside the JSX
// Goodif (!user) {return <Login />;}// Good<p>{isOnline ? "Online" : "Offline"}</p>
10. Logical AND &&
Another very common React pattern is:
{condition && <Component />}
function Notifications({ hasNotifications }: { hasNotifications: boolean }) {return (<div>{hasNotifications && <NotificationBadge />}</div>);}
If hasNotifications is true, the badge appears. If false, it doesn't.
11. Why Does && Work?
JavaScript evaluates true && value as value, and false && value as false.
React doesn't render false as visible UI.
{isLoggedIn && <Dashboard />}// Render Dashboard only when isLoggedIn is truthy.
12. Example: Show a Logout Button
function Header({ isLoggedIn }: { isLoggedIn: boolean }) {return (<header><h1>My Website</h1>{isLoggedIn && <button>Logout</button>}</header>);}
13. && Is Best for One-Sided Conditions
Use {isAdmin && <AdminPanel />} when you mean: show this if the condition is true.
If you need true → A and false → B, use a ternary:
{isAdmin ? <AdminPanel /> : <UserPanel />}
14. Important && Pitfall: Numbers
Be careful with:
{count && <p>Messages available</p>}
If count = 0, the expression evaluates to 0, and React can render the 0.
Instead, use an explicit comparison:
{count > 0 && <p>Messages available</p>}
This is an important React conditional-rendering rule.
15. Logical OR ||
function Greeting({ name }: { name?: string }) {return <h1>Hello, {name || "Guest"}</h1>;}
If name is missing or falsy, "Guest" is used.
Remember || treats false, 0, "", null, undefined, and NaN as falsy.
16. Nullish Coalescing ??
Sometimes ?? is better than ||.
function Price({ price }: { price?: number | null }) {return <p>Price: {price ?? "Not available"}</p>;}
With price = 0, the value 0 is preserved. price || "Not available" would treat 0 as falsy. ?? only falls back for null and undefined.
17. Rendering Nothing
Sometimes the correct UI is nothing.
function AdminPanel({ isAdmin }: { isAdmin: boolean }) {if (!isAdmin) {return null;}return (<section><h2>Admin Panel</h2></section>);}
Non-admin users don't get any visible output from this component.
18. Conditional Rendering with State
import { useState } from "react";function Toggle() {const [isOpen, setIsOpen] = useState(false);return (<div><button onClick={() => setIsOpen(!isOpen)}>Toggle</button>{isOpen && <p>The content is visible.</p>}</div>);}
isOpen = false↓content hidden↓user clicks↓setIsOpen(true)↓component re-renders↓content appears
19. Conditional Rendering with Props
function Button({isDisabled,children,}: {isDisabled?: boolean;children: React.ReactNode;}) {return <button disabled={isDisabled}>{children}</button>;}<Button isDisabled>Save</Button>
20. Conditional Attributes
function SubmitButton({ isLoading }: { isLoading: boolean }) {return <button disabled={isLoading}>Submit</button>;}
If isLoading = true, the button is disabled.
21. Conditional Text
function Button({ isLoading }: { isLoading: boolean }) {return <button>{isLoading ? "Saving..." : "Save"}</button>;}
22. Conditional Classes
function Status({ isActive }: { isActive: boolean }) {return (<span className={isActive ? "status active" : "status inactive"}>{isActive ? "Active" : "Inactive"}</span>);}
23. Conditional Classes with Template Literals
function Button({ variant }: { variant: string }) {return <button className={`button ${variant}`}>Save</button>;}<Button variant="primary" /><Button variant="danger" />
24. Conditional Components
function Page({ isLoggedIn }: { isLoggedIn: boolean }) {if (isLoggedIn) {return <Dashboard />;}return <Login />;}function PageAlt({ isAdmin }: { isAdmin: boolean }) {return <>{isAdmin ? <AdminDashboard /> : <UserDashboard />}</>;}
25. Loading States
function ProductList({isLoading,products,}: {isLoading: boolean;products: { id: number; name: string }[];}) {if (isLoading) {return <p>Loading products...</p>;}return (<ul>{products.map((product) => (<li key={product.id}>{product.name}</li>))}</ul>);}
Loading → Loading messageLoaded → Product list
26. Loading + Error + Success
function Products({isLoading,error,products,}: {isLoading: boolean;error?: string | null;products: { id: number; name: string }[];}) {if (isLoading) {return <p>Loading...</p>;}if (error) {return <p>Unable to load products.</p>;}return (<ul>{products.map((product) => (<li key={product.id}>{product.name}</li>))}</ul>);}
Products│┌────────┼────────┐↓ ↓ ↓Loading Error Success↓ ↓ ↓Spinner Message List
This pattern appears everywhere in React applications.
27. Empty States
function ProductList({ products }: { products: { id: number; name: string }[] }) {if (products.length === 0) {return <p>No products found.</p>;}return (<ul>{products.map((product) => (<li key={product.id}>{product.name}</li>))}</ul>);}
This gives you Loading, Error, Empty, and Success as separate UI states.
28. Authentication Example
function App({ user }: { user: unknown }) {if (!user) {return <LoginPage />;}return <Dashboard user={user} />;}
29. Permission Example
function Settings({ user }: { user: { isAdmin: boolean } }) {return (<section><h1>Settings</h1>{user.isAdmin && <AdminSettings />}</section>);}
30. Multiple Conditions with Ternaries
You can technically write nested ternaries, but they quickly become hard to read.
function Status({ status }: { status: string }) {return (<p>{status === "loading"? "Loading...": status === "error"? "Something went wrong.": "Success!"}</p>);}
For multiple states, prefer clearer logic.
31. Better Alternative: Early Returns
function Status({ status }: { status: string }) {if (status === "loading") {return <p>Loading...</p>;}if (status === "error") {return <p>Something went wrong.</p>;}return <p>Success!</p>;}
32. Multiple Conditions Inside JSX
function Dashboard({isLoggedIn,isAdmin,}: {isLoggedIn: boolean;isAdmin: boolean;}) {return (<main>{isLoggedIn && <UserMenu />}{isLoggedIn && isAdmin && <AdminPanel />}</main>);}
33. Conditional Rendering with Functions
function getStatusMessage(status: string) {if (status === "loading") return "Loading...";if (status === "error") return "Something went wrong.";return "Ready";}function Status({ status }: { status: string }) {return <p>{getStatusMessage(status)}</p>;}
34. Conditional Rendering with Variables
function UserProfile({ user }: { user: unknown }) {let content;if (!user) {content = <Login />;} else {content = <Profile user={user} />;}return <main>{content}</main>;}
35. Conditional Rendering with switch
function Status({ status }: { status: string }) {switch (status) {case "loading":return <Loading />;case "error":return <ErrorMessage />;case "empty":return <EmptyState />;case "success":return <Success />;default:return <UnknownState />;}}
36. Conditional Rendering Is Just JavaScript
React doesn't have a completely separate conditional syntax.
You use JavaScript (if, ternary, &&, ||, ??, switch, variables, functions) to determine what JSX should be returned.
JavaScript condition↓Choose React element(s)↓React renders them
37. Conditional Rendering and Component State
const [isLoggedIn, setIsLoggedIn] = useState(false);return <>{isLoggedIn ? <Dashboard /> : <Login />}</>;// Later:setIsLoggedIn(true);// → isLoggedIn = true → Dashboard
38. Conditional Rendering with Forms
function LoginForm({ isSubmitted }: { isSubmitted: boolean }) {if (isSubmitted) {return <p>Login successful!</p>;}return <form>{/* form fields */}</form>;}
39. Conditional Rendering with Permissions
function Protected({allowed,children,}: {allowed: boolean;children: React.ReactNode;}) {if (!allowed) {return null;}return children;}<Protected allowed={user.isAdmin}><AdminPanel /></Protected>
This is composition + props + conditional rendering.
40. Conditional Rendering with Feature Flags
function HomePage({ newDashboardEnabled }: { newDashboardEnabled: boolean }) {return <>{newDashboardEnabled ? <NewDashboard /> : <OldDashboard />}</>;}
41. Conditional Rendering and Accessibility
Don't simply hide UI with CSS when the element should not exist in the interface.
{isLoggedIn && <LogoutButton />}
is different from rendering the button and merely hiding it visually. Conditional rendering should reflect whether an element should actually participate in the UI.
42-48. Common Mistakes
Nested ternaries
Avoid deeply nested ternaries. Prefer early returns or extracted functions.
Misusing &&
// Bad when length can be 0{items.length && <List />}// Prefer{items.length > 0 && <List />}
Confusing || with ??
{count || "No count"} // 0 becomes "No count"{count ?? "No count"} // 0 is preserved
Hiding logic in JSX
Extract complex conditions into variables or functions.
Mixing too many responsibilities
Extract meaningful components so conditional rendering stays clear.
Forgetting loading / empty states
Consider Loading, Error, Empty, and Success separately.
Treating all conditions the same
Match the pattern to the situation: ternary, &&, if, or switch.
49. Best Practices
- Prefer simple conditions.
- Use early returns for major UI branches.
- Use ternaries for simple two-way choices.
- Use
&&for one-sided rendering. - Be careful with
0and&&. - Use
??when0or""should remain valid. - Avoid deeply nested ternaries.
- Extract complex conditions into variables or functions.
- Handle loading, error, empty, and success states.
- Keep conditional logic readable.
- Use components to isolate complex UI states.
- Don't introduce unnecessary abstraction.
50. Complete Example: Product Page
function ProductPage({isLoading,error,product,}: {isLoading: boolean;error?: string | null;product?: { name: string; price: number; inStock: boolean; isFeatured?: boolean } | null;}) {if (isLoading) {return <p>Loading product...</p>;}if (error) {return <p>Unable to load product.</p>;}if (!product) {return <p>Product not found.</p>;}return (<article><h1>{product.name}</h1><p>INR {product.price}</p>{product.inStock ? (<button>Add to Cart</button>) : (<p>Currently unavailable</p>)}{product.isFeatured && <span>Featured Product</span>}</article>);}
51. Complete Example: Authentication
function App({ user }: { user?: { isAdmin?: boolean } | null }) {if (!user) {return <LoginPage />;}return (<main><Navbar user={user} /><Dashboard user={user} />{user.isAdmin && <AdminPanel />}</main>);}
52. Complete Example: Shopping Cart
function Cart({ items }: { items: { id: number; name: string; price: number }[] }) {if (items.length === 0) {return (<section><h2>Your Cart</h2><p>Your cart is empty.</p></section>);}return (<section><h2>Your Cart</h2>{items.map((item) => (<div key={item.id}><h3>{item.name}</h3><p>INR {item.price}</p></div>))}<button>Checkout</button></section>);}
53. Complete Example: Status Component
function StatusMessage({ status }: { status: string }) {if (status === "loading") return <Loading />;if (status === "error") return <ErrorMessage />;if (status === "empty") return <EmptyState />;if (status === "success") return <SuccessMessage />;return <p>Unknown status.</p>;}
54-55. Practical Exercises
Exercise 1: UserStatus
Receive isLoggedIn and isAdmin. Show "Please log in", "Welcome User", or "Welcome Admin".
function UserStatus({isLoggedIn,isAdmin,}: {isLoggedIn: boolean;isAdmin: boolean;}) {if (!isLoggedIn) {return <p>Please log in</p>;}if (isAdmin) {return <p>Welcome Admin</p>;}return <p>Welcome User</p>;}
Exercise 2: ProductList states
Handle loading, error, empty, and success for a product list.
function ProductList({isLoading,error,products,}: {isLoading: boolean;error?: string | null;products: { id: number; name: string }[];}) {if (isLoading) return <p>Loading products...</p>;if (error) return <p>Unable to load products.</p>;if (products.length === 0) return <p>No products found.</p>;return (<ul>{products.map((product) => (<li key={product.id}>{product.name}</li>))}</ul>);}
56. Interview Questions
Q1. What is conditional rendering in React?
Rendering different React elements or components depending on application state, props, or other conditions, using normal JavaScript constructs.
Q2. How do you conditionally render a component?
if (isLoggedIn) return <Dashboard />;{isLoggedIn ? <Dashboard /> : <Login />}{isAdmin && <AdminPanel />}
Q3. When should you use a ternary?
When there are two relatively simple UI alternatives.
Q4. When should you use &&?
When you want to render something only when a condition is truthy and need no alternative UI.
Q5. What is the problem with {count && <Component />}?
If count is 0, React can render 0. Prefer {count > 0 && <Component />}.
Q6. How do you render nothing in React?
Return null.
Q7. Can conditional rendering depend on props?
Yes. Props commonly drive which UI branch appears.
Q8. Can conditional rendering depend on state?
Yes. Updating state causes React to render the appropriate UI again.
57. The Three Most Important Patterns
Pattern 1 — if
if (!user) {return <Login />;}return <Dashboard />;
Pattern 2 — Ternary
{isOnline ? "Online" : "Offline"}
Pattern 3 — &&
{isAdmin && <AdminPanel />}
Master these three and you'll handle most everyday conditional rendering.
58. Conditional Rendering Mental Model
Props+State│▼Condition(s)│┌───────┼───────┐▼ ▼ ▼Loading Error Success│ │ │▼ ▼ ▼Loading Error DataUI UI UI
You express the conditions, and React renders the resulting UI.
59. Final Cheat Sheet
// ifif (!user) return <Login />;// ternary{isLoggedIn ? <Dashboard /> : <Login />}// &&{isAdmin && <AdminPanel />}// ||{name || "Guest"}// ??{price ?? "Not available"}// nothingreturn null;// attribute<button disabled={isLoading}>// text{isLoading ? "Saving..." : "Save"}// classclassName={isActive ? "active" : "inactive"}// multiple statesif (isLoading) return <Loading />;if (error) return <Error />;if (!items.length) return <Empty />;return <List items={items} />;
Key Takeaway
Conditional rendering allows React components to adapt their UI to changing data, props, and state.
if↓Major UI branchesternary↓Two alternatives&&↓Optional UInull↓Render nothing
And in a real application, think in terms of UI states:
Loading↓Error↓Empty↓Success
A strong React developer doesn't just ask "What should this component render?" They also ask: "What UI should the user see in every possible state of this component?"
That mindset leads naturally into the next major React concepts: Rendering Lists, Handling Events, and Managing State.