Conditional rendering
A logged-in visitor sees a dashboard, a logged-out visitor sees a login form, and a failed request needs an error message to show up somewhere on the page. A boolean like isLoggedIn usually lives in state, and what changes is which piece of UI gets rendered for its current value. JSX is JavaScript, so deciding what to render works the same way any other decision in your code works: an expression that picks a value, evaluated right there in the return statement.
Choosing between two elements with a ternary
When there are exactly two things a piece of UI could be, the ternary operator picks between them:
return (
<div>
{isLoggedIn ? <Dashboard /> : <Login />}
{hasError && <p>Something went wrong</p>}
</div>
)isLoggedIn ? <Dashboard /> : <Login /> reads the same as any other ternary: if isLoggedIn is true, this expression evaluates to <Dashboard />, otherwise it evaluates to <Login />. Whatever it evaluates to gets rendered in that spot in the JSX. Curly braces are what let you drop a JavaScript expression into the middle of markup, and a ternary is one expression like any other.
Showing or hiding one element with &&
The second line handles a different shape of decision: show something, or show nothing. hasError && <p>Something went wrong</p> uses the && operator the way it works everywhere else in JavaScript. If hasError is false, && short-circuits and the whole expression evaluates to false, without ever reaching the JSX on the right. If hasError is true, the expression evaluates to the <p> element.
The reason this renders correctly comes down to what React does with the result. React skips rendering anything for false, null, and undefined, so when hasError is false, nothing shows up on the page at all.
The falsy value gotcha
&& doesn't only produce true or false. Like any JavaScript expression using &&, it evaluates to whichever side it lands on, and that side can be any value, not necessarily a boolean. Most of the time that's harmless, but it turns into a bug when the left side is a number:
{count && <Badge />}
// count = 0 → renders "0" on the pageIf count is 0, this expression evaluates to 0. React skips rendering for false, null, and undefined, but 0 is a real, renderable value, so React puts it on the page. The badge doesn't show, but a stray 0 does, sitting right where you expected nothing.
The fix is to make sure the left side of && is always an actual boolean:
{count > 0 && <Badge />}
// count = 0 → renders nothingcount > 0 always evaluates to true or false, so the expression either renders the badge or renders nothing, with no 0 left behind.
Rendering nothing at all
Sometimes a component has nothing to show, and the clearest way to say that is to return early:
function Banner({ message }) {
if (!message) {
return null
}
return <p className="banner">{message}</p>
}When message is empty, the function returns null before it ever builds the rest of the JSX. That keeps the main return focused on the case where there's actually something to render, instead of wrapping the whole thing in one more condition.
&& shows one element or shows nothing, and returning null from a component is how you say "there's nothing to render here." Watch out for {count && <Badge />} when count can be 0, since 0 is a value React will actually print. Writing {count > 0 && <Badge />} instead keeps the left side a true boolean. Next up: Forms, where you'll use state to handle input fields.

