Conditional Rendering
Showing different output for different data, using ordinary JavaScript rather than special syntax.
An early return
The clearest option when whole branches differ is a plain if before the JSX.
function Status({ user }) {
if (!user) {
return <p>Please sign in.</p>;
}
return <p>Signed in as {user.name}</p>;
}The ternary operator
Inside JSX you need an expression, so a conditional becomes a ternary.
function Status({ isOnline }) {
return (
<p className={isOnline ? "online" : "offline"}>
{isOnline ? "Online" : "Offline"}
</p>
);
}Ternaries nest, but two levels is usually the point at which a variable or a separate component reads better.
Logical AND for show-or-nothing
function Inbox({ unread }) {
return (
<div>
<h2>Inbox</h2>
{unread > 0 && <span className="badge">{unread} new</span>}
</div>
);
}There is a trap here. If the left side is the number 0, React renders the zero instead of nothing, because 0 && x evaluates to 0 and React renders numbers.
// Renders a stray "0" when items is empty
{items.length && <List items={items} />}
// Renders nothing when items is empty
{items.length > 0 && <List items={items} />}false, null, undefined, and true all render as nothing. Numbers and strings render as themselves — which is why 0 leaks through.
Assigning to a variable
When several conditions combine, building the element in a variable keeps the returned JSX readable.
function Message({ status }) {
let content;
if (status === "loading") {
content = <Spinner />;
} else if (status === "error") {
content = <p className="error">Could not load. Try again.</p>;
} else {
content = <Report />;
}
return <div className="panel">{content}</div>;
}Switching on a value
For a fixed set of cases, an object map is compact and avoids a chain of comparisons.
const icons = {
success: <CheckIcon />,
warning: <AlertIcon />,
error: <CrossIcon />,
};
function Notice({ kind, children }) {
return (
<div className={`notice notice-${kind}`}>
{icons[kind] ?? null}
{children}
</div>
);
}Conditional attributes
The same expressions work inside attributes.
<button
className={isActive ? "tab tab-active" : "tab"}
disabled={isSaving}
aria-current={isActive ? "page" : undefined}
>
Overview
</button>Passing undefined removes an attribute entirely, which is often what you want for ARIA attributes.