Conditional Rendering
Workplace Context
Many web applications need to display different information or UI elements depending on the current situation. For example, you might need to:
- Show a “Loading…” message while data is being fetched.
- Display a user’s profile information only if they are logged in.
- Render an “Edit” button only if the user has permission.
- Show an error message if a form submission fails.
- Toggle between a compact view and a detailed view of an item.
React provides several straightforward ways to handle this conditional rendering, allowing you to control exactly what gets displayed based on your component’s props or state.
Learning Objectives
By the end of this lesson, learners will be able to:
- Explain why conditional rendering is necessary in dynamic UIs.
- Implement conditional rendering using JavaScript
if/elsestatements outside of JSX blocks. - Implement conditional rendering directly within JSX using the ternary operator (
condition ? exprIfTrue : exprIfFalse). - Implement conditional rendering directly within JSX using the logical AND operator (
condition && exprIfTrue) for short-circuit evaluation. - Return
nullfrom a component or within JSX to render nothing. - Choose appropriate conditional rendering techniques based on the complexity of the logic.
Why Conditional Rendering?
Static websites display the same content to every user every time. Modern web applications, however, are dynamic. The UI needs to adapt based on:
- User Status: Logged in vs. logged out, admin vs. regular user.
- Data Availability: Loading data, data loaded successfully, error fetching data.
- User Interaction: Showing/hiding menus, revealing details, displaying success/error messages after actions.
- Application State: Different modes or views within the application.
Conditional rendering is the mechanism React uses to handle these scenarios, ensuring the correct UI is presented for the current conditions.
Using if/else Statements
JavaScript if/else statements cannot be used directly inside JSX curly braces {} because JSX expects an expression (something that evaluates to a value), while if is a statement (performs an action).
However, you can use if/else outside your JSX blocks to determine which JSX structure to render. You can assign JSX to variables and then return the chosen variable.
import { useState } from 'react';
interface LoginMessageProps {
isLoggedIn: boolean;
}
function LoginMessage({ isLoggedIn }: LoginMessageProps) {
// Use if/else outside the return statement
let messageElement: React.ReactNode; // Type can hold JSX or null
if (isLoggedIn) {
messageElement = <h2>Welcome back!</h2>;
} else {
messageElement = <h2>Please log in.</h2>;
}
// Return the chosen JSX element
return <div>{messageElement}</div>;
}
// Example Usage Component
function ConditionalWithIfElse() {
const [loggedIn, setLoggedIn] = useState(false);
return (
<div>
<LoginMessage isLoggedIn={loggedIn} />
<button onClick={() => setLoggedIn(prev => !prev)}>
Toggle Login Status
</button>
</div>
)
}
export default ConditionalWithIfElse;This approach is clear and suitable when the conditional logic is complex or involves rendering entirely different component structures based on the condition. You can even return different components entirely from within the if/else blocks.
Using the Ternary Operator (? :)
The JavaScript ternary conditional operator (condition ? valueIfTrue : valueIfFalse) is an expression, meaning it evaluates to a value. Therefore, it can be used directly inside JSX curly braces {}. This is often the most concise way to handle simple conditional rendering.
Syntax: { condition ? <JSX_If_True /> : <JSX_If_False /> }
import { useState } from 'react';
function LoginButton({ isLoggedIn, onLoginLogout }) {
return (
<button onClick={onLoginLogout}>
{/* Use ternary operator directly inside JSX */}
{isLoggedIn ? 'Log Out' : 'Log In'}
</button>
);
}
function GreetingText({ isLoggedIn }) {
return (
<p>
{/* Use ternary for conditional text */}
{isLoggedIn ? 'You are currently logged in.' : 'Please log in to continue.'}
</p>
);
}
// Example Usage Component
function ConditionalWithTernary() {
const [loggedIn, setLoggedIn] = useState(false);
return (
<div>
<GreetingText isLoggedIn={loggedIn} />
<LoginButton isLoggedIn={loggedIn} onLoginLogout={() => setLoggedIn(prev => !prev)} />
</div>
)
}
export default ConditionalWithTernary;The ternary operator is excellent for choosing between two relatively simple JSX outputs based on a single condition.
Using Logical AND (&&) - Short-Circuiting
Sometimes, you only want to render something if a condition is true, and render nothing otherwise. You could use a ternary operator (condition ? <JSX /> : null), but a more concise way is to use the JavaScript logical AND operator (&&).
This relies on short-circuit evaluation:
- If
conditionisfalse(or falsy like0,null,undefined), the expression immediately evaluates tofalse, and React renders nothing. - If
conditionistrue(or truthy), the expression evaluates to the value after the&&, which is your JSX element. React then renders that element.
Syntax: { condition && <JSX_If_Condition_Is_True /> }
import { useState } from 'react';
function Mailbox({ unreadMessages }) {
const messageCount = unreadMessages.length;
return (
<div>
<h2>Mailbox</h2>
{/* Only render the message count paragraph if messageCount > 0 */}
{messageCount > 0 &&
<p>You have {messageCount} unread messages.</p>
}
{messageCount === 0 &&
<p>No unread messages.</p>
}
{/* Demonstrating with a boolean */}
{true && <p>This will always render.</p>}
{false && <p>This will never render.</p>}
</div>
);
}
// Example Usage Component
function ConditionalWithAnd() {
const [messages, setMessages] = useState(['msg1', 'msg2']);
return (
<div>
<Mailbox unreadMessages={messages} />
<button onClick={() => setMessages([])}>Mark All Read</button>
<button onClick={() => setMessages(['msg1', 'msg2', 'msg3'])}>Receive New</button>
</div>
)
}
export default ConditionalWithAnd;Be mindful of using 0 with &&. If you write {count && <p>Items: {count}</p>}, and count becomes 0, React will render 0 on the screen because 0 is the result of the expression (it is falsy, but renderable). To avoid this, ensure the condition is strictly boolean (count > 0 && ...) or use a ternary operator (count > 0 ? <p>Items: {count}</p> : null).
Returning null to Render Nothing
You can explicitly return null from a component’s render logic if you do not want it to render anything under certain conditions. This is perfectly valid.
interface WarningBannerProps {
showWarning: boolean;
message: string;
}
function WarningBanner({ showWarning, message }: WarningBannerProps) {
// If showWarning is false, the component renders nothing
if (!showWarning) {
return null;
}
// Otherwise, render the warning div
return (
<div style={{ backgroundColor: 'yellow', padding: '10px', border: '1px solid orange' }}>
Warning: {message}
</div>
);
}
// Example Usage Component
function ConditionalWithNull() {
const [warningVisible, setWarningVisible] = useState(true);
return (
<div>
<WarningBanner showWarning={warningVisible} message="This is an important warning!" />
<button onClick={() => setWarningVisible(prev => !prev)}>
Toggle Warning
</button>
{!warningVisible && <p>(Warning banner is currently hidden because it returned null)</p>}
</div>
)
}
export default ConditionalWithNull;Returning null is useful for components whose sole purpose is conditional display, or when the logic using if/else makes returning null the cleanest “do nothing” option.
Strategies and Choosing the Right Technique
if/else: Best when the logic is complex, involves multiple conditions, or when you need to render entirely different component structures or returnnull. Keep it outside the JSX.- Ternary (
? :): Ideal for simple, inline choices between two possible outputs within JSX. - Logical AND (
&&): Great for concisely rendering an element only if a condition is true (or rendering nothing otherwise). Be careful with non-boolean conditions like0. nullReturn: A clean way for a component to opt-out of rendering altogether based on props or state.
You can also improve readability by extracting complex conditional logic into separate variables or even separate components.
Example: Extracting to a variable
function UserStatus({ user }) {
let statusIndicator;
if (user.isAdmin) {
statusIndicator = <span style={{ color: 'red' }}>Admin</span>;
} else if (user.isActive) {
statusIndicator = <span style={{ color: 'green' }}>Active</span>;
} else {
statusIndicator = <span style={{ color: 'grey' }}>Inactive</span>;
}
return (
<div>
User: {user.name} - Status: {statusIndicator}
</div>
);
}Activity 1: Show/Hide with Ternary and &&
Create a component Toggler with:
- A state variable
isOn(boolean), initiallyfalse. - A button that toggles the
isOnstate when clicked. - A paragraph that displays “Status: ON” if
isOnis true, and “Status: OFF” ifisOnis false (use the ternary operator). - Another element (e.g., a
<div>with a background color) that only appears ifisOnis true (use the&&operator).
Completed Example
Status: OFF
Activity 2: Different Content with if/else
Create a component ContentSwitcher with:
- A state variable
contentType(string), which can be'text','image', or'video'. - Three buttons: “Show Text”, “Show Image”, “Show Video”. Clicking a button updates the
contentTypestate accordingly. - Use
if/else if/elsestatements outside the return statement to define acontentElementvariable based on thecontentTypestate.- If
'text',contentElementshould be<p>This is some text content.</p>. - If
'image',contentElementshould be<img src="https://via.placeholder.com/150" alt="Placeholder" />. - If
'video',contentElementshould be<p>Imagine a video player here.</p>(we won’t embed a real one).
- If
- Render the
contentElementwithin the component’s returned JSX.
Completed Example
This is some text content.
You can add more text here to demonstrate the text view.
Knowledge Check
Which conditional rendering technique is best suited for choosing between two simple JSX elements directly within the return statement?
- Select an answer to view feedback.
What happens when you use the logical AND (&&) operator like { count && <p>{count}</p> } and the count state variable is 0?
- Select an answer to view feedback.
If you want a component to render absolutely nothing based on a prop or state condition, what should the component return?
- Select an answer to view feedback.
When is using if/else statements outside the JSX return block generally preferred?
- Select an answer to view feedback.
Summary
In this lesson, you explored various techniques for conditional rendering in React. You learned how to use if/else statements outside JSX for complex logic, the ternary operator (? :) for concise inline choices, and the logical AND operator (&&) for rendering elements only when a condition is true. You also saw how returning null effectively prevents a component from rendering. Choosing the right technique depends on the specific scenario and complexity, but mastering these patterns is essential for building dynamic and responsive user interfaces.
References
- React Docs: Conditional Rendering
- MDN: Conditional (ternary) operator
- MDN: Logical AND (
&&) (Explains short-circuiting)
Additional Resources
- Conditional Rendering in React (Blog post with various examples)