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
/else
statements 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
null
from 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
condition
isfalse
(or falsy like0
,null
,undefined
), the expression immediately evaluates tofalse
, and React renders nothing. - If
condition
istrue
(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
. null
Return: 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
isOn
state when clicked. - A paragraph that displays “Status: ON” if
isOn
is true, and “Status: OFF” ifisOn
is false (use the ternary operator). - Another element (e.g., a
<div>
with a background color) that only appears ifisOn
is 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
contentType
state accordingly. - Use
if/else if/else
statements outside the return statement to define acontentElement
variable based on thecontentType
state.- If
'text'
,contentElement
should be<p>This is some text content.</p>
. - If
'image'
,contentElement
should be<img src="https://via.placeholder.com/150" alt="Placeholder" />
. - If
'video'
,contentElement
should be<p>Imagine a video player here.</p>
(we won’t embed a real one).
- If
- Render the
contentElement
within 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)