Conditional Rendering
Level: Beginner
- if/else inside render for complex conditionals
- Ternary operator for inline conditions
- Logical && operator for simple show/hide
- Logical || for fallback UI
- Conditional return for early exit
- Handling loading, error, and empty states
- Combining conditions for complex UI logic
- SMS patterns: showing fees only if unpaid, hiding edit button from students, etc.
Why This Matters
Conditional Rendering is part of building maintainable React applications. You will use it when creating student dashboards, forms, tables, API-connected screens, routing flows, and reusable UI components.
Different users see different UI. Use conditional rendering to show/hide elements based on state, props, or data.
The Problem
Beginners often write React code that works for a small demo but becomes difficult when data, forms, API calls, and reusable components grow. This lesson explains Conditional Rendering in a way that helps you build predictable UI for real .NET Web API projects.
Basic Patterns
if/else Statement
function StudentStatus({ student }) {
if (student.status === 'Active') {
return <div className="active">✓ Active</div>;
} else if (student.status === 'Graduated') {
return <div className="graduated">✓ Graduated</div>;
} else {
return <div className="inactive">✗ Inactive</div>;
}
}
Ternary Operator
function StudentStatus({ student }) {
return (
<div>
{student.status === 'Active' ? (
<span className="active">Active</span>
) : (
<span className="inactive">Inactive</span>
)}
</div>
);
}
Logical AND (&&)
Show if condition is true, nothing otherwise.
function StudentApproval({ student }) {
return (
<div>
{student.isApproved && (
<div className="badge">✓ Approved</div>
)}
</div>
);
}
// Also works with variables
{isAdmin && <button>Delete User</button>}
{hasError && <p className="error">{errorMessage}</p>}
Logical OR (||)
Show first if falsy, second otherwise (default value pattern).
function StudentName({ student }) {
return <h1>{student.name || 'Unknown Student'}</h1>;
}
Common Patterns
Pattern 1: Loading State
function StudentDetail({ studentId }) {
const [student, setStudent] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`/api/students/${studentId}`)
.then(r => r.json())
.then(data => {
setStudent(data);
setLoading(false);
});
}, [studentId]);
if (loading) {
return <p>Loading...</p>;
}
return <div>{student.name}</div>;
}
Pattern 2: Error State
function StudentDetail({ studentId }) {
const [student, setStudent] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
fetch(`/api/students/${studentId}`)
.then(r => r.json())
.then(data => setStudent(data))
.catch(err => setError(err.message));
}, [studentId]);
if (error) {
return <p className="error">Error: {error}</p>;
}
if (!student) {
return <p>Loading...</p>;
}
return <div>{student.name}</div>;
}
Pattern 3: Empty State
function StudentList({ students }) {
if (students.length === 0) {
return (
<div className="empty">
<p>No students found.</p>
<button>Add New Student</button>
</div>
);
}
return (
<ul>
{students.map(student => (
<li key={student.id}>{student.name}</li>
))}
</ul>
);
}
Pattern 4: Permission-Based Rendering
function StudentActions({ user, student }) {
return (
<div>
{/* Everyone sees this */}
<button>View Details</button>
{/* Only teachers see this */}
{user.role === 'Teacher' && (
<button>Edit Marks</button>
)}
{/* Only admins see this */}
{user.role === 'Admin' && (
<>
<button>Edit Student</button>
<button>Delete Student</button>
</>
)}
</div>
);
}
Complete Example: Student Dashboard
function StudentDashboard({ studentId, currentUser }) {
const [student, setStudent] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [showDetails, setShowDetails] = useState(false);
useEffect(() => {
fetch(`/api/students/${studentId}`)
.then(r => r.json())
.then(data => {
setStudent(data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, [studentId]);
// Show loading state
if (loading) {
return <div className="loading">Loading student data...</div>;
}
// Show error state
if (error) {
return (
<div className="error">
<p>Failed to load student: {error}</p>
<button onClick={() => window.location.reload()}>Retry</button>
</div>
);
}
// No student found
if (!student) {
return <div className="empty">Student not found.</div>;
}
// Render student data
return (
<div className="dashboard">
<div className="header">
<h1>{student.name}</h1>
{student.status === 'Active' && (
<span className="badge-active">Active</span>
)}
{student.status === 'Graduated' && (
<span className="badge-graduated">Graduated</span>
)}
</div>
<div className="content">
<p>Class: {student.className}</p>
<p>Roll: {student.rollNumber}</p>
{/* Show parents contact only to admins/parents */}
{(currentUser.role === 'Admin' || currentUser.id === student.parentId) && (
<div className="parent-info">
<p>Parent: {student.parentName}</p>
<p>Phone: {student.parentPhone}</p>
</div>
)}
{/* Show button to expand details */}
<button onClick={() => setShowDetails(!showDetails)}>
{showDetails ? 'Hide Details' : 'Show Details'}
</button>
{/* Show detailed info if expanded */}
{showDetails && (
<div className="details">
<p>Date of Birth: {student.dob}</p>
<p>Address: {student.address}</p>
<p>Fees Status: {student.feeStatus}</p>
</div>
)}
</div>
{/* Action buttons based on role */}
<div className="actions">
{currentUser.role === 'Teacher' && (
<button>View Marks</button>
)}
{currentUser.role === 'Admin' && (
<>
<button>Edit Student</button>
<button>View Payments</button>
<button className="danger">Delete</button>
</>
)}
</div>
</div>
);
}
Avoiding Common Mistakes
❌ Don't: Ternary with No Else
// This renders "false" or "true" as text!
{condition ? <div>Yes</div> : false}
// Better: use null
{condition ? <div>Yes</div> : null}
// Or: use && instead
{condition && <div>Yes</div>}
❌ Don't: Object/Array as Condition
// ❌ Wrong — renders "[object Object]"
{student && <div>{student}</div>}
// ✓ Correct
{student && <div>{student.name}</div>}
❌ Don't: JSX in Condition
// ❌ Wrong — JSX in if statement
if (student) {
return (
<div>{student.name}</div>
<div>Details...</div> // Multiple elements, syntax error
);
}
// ✓ Correct — wrap in fragment
if (student) {
return (
<>
<div>{student.name}</div>
<div>Details...</div>
</>
);
}
Switch Statement (for Many Conditions)
function StudentStatusBadge({ status }) {
switch (status) {
case 'Active':
return <span className="badge-green">Active</span>;
case 'Graduated':
return <span className="badge-blue">Graduated</span>;
case 'Inactive':
return <span className="badge-red">Inactive</span>;
case 'Transferred':
return <span className="badge-orange">Transferred</span>;
default:
return <span className="badge-gray">Unknown</span>;
}
}
Or cleaner with object:
function StudentStatusBadge({ status }) {
const badges = {
'Active': <span className="badge-green">Active</span>,
'Graduated': <span className="badge-blue">Graduated</span>,
'Inactive': <span className="badge-red">Inactive</span>,
'Transferred': <span className="badge-orange">Transferred</span>,
'Default': <span className="badge-gray">Unknown</span>
};
return badges[status] || badges['Default'];
}
Key Takeaways
- Use && to show if true
- Use ternary for if/else
- Handle loading and error states
- Show/hide based on permissions
- Next: Error handling and boundaries
- Rendering objects/arrays — Must access properties
- No loading state — UI looks broken while loading
- No error state — Users don't know what went wrong
- Not checking for null — Crashes on null/undefined
Instead of "Loading...", show a fake card (skeleton) that looks like the real content:
if (loading) {
return (
<div className="skeleton">
<div className="skeleton-header" />
<div className="skeleton-text" />
</div>
);
}
Use ChatGPT, Claude, or Copilot to go deeper on Conditional Rendering. Try these prompts:
"When would you use && vs. ternary operator?""Why should you always handle loading and error states?""How do you conditionally show content based on user role?""Quiz me on conditional rendering"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.
Quick Definitions
- Conditional Rendering - The main React concept explained in this lesson.
- Component - A reusable function that returns UI.
- Props/state/effects - Core React ideas used to pass data, remember data, and run side effects.
- Real project usage - How this appears in forms, dashboards, routes, and API-connected pages.
Common Mistakes
- Copying React code without understanding data flow
- Mutating arrays or objects directly instead of creating new values
- Forgetting keys, dependencies, loading states, or error states where needed
- Putting too much logic in one component
- Not testing the screen with realistic School Management System data
Practice Task
Create a small React example using Conditional Rendering. Keep it focused on one School Management System screen.
Suggested practice:
- Build a small component or page for students, attendance, marks, or fees.
- Pass realistic data into the component.
- Add one success state and one empty/error state where relevant.
- Explain the data flow in your own words.
- Rebuild the same example once without looking at the article.
Quick Revision
| Question | Answer |
|---|---|
| What is the main idea? | Understand and apply Conditional Rendering in React. |
| Where is it used? | Student dashboards, forms, tables, routes, and API-connected screens. |
| What should beginners focus on? | Clear components, predictable data flow, and small examples. |
| What is the best debugging habit? | Check props, state, render output, and browser console step by step. |
Conditional Rendering is a React concept used to build clear, reusable, and predictable user interfaces. I would explain the problem it solves, show a small component example, and mention a common mistake beginners should avoid.
It is used in screens like student lists, admission forms, attendance dashboards, marks reports, routing pages, and API-connected admin panels.