Conditional Rendering

There is no v-if and no {{#if}} in JSX, because JavaScript already has conditionals. Four tools, in rough order of preference: return null early when the component should render nothing; assign markup to a variable with a normal if before the return; use a ternary inside the braces; or use && when there is no "else" branch. React 7,897 treats null, undefined, false and true as children that render nothing, which is what makes all four work.

The && form has one famous trap. expr && <JSX/> evaluates to the left operand when that operand is falsy, and React renders a number, so items.length && <List/> prints a bare 0 on an empty list. Compare the count instead: items.length > 0 && ....

Four ways to render conditionally, and the falsy-zero trapHTMLLive
<div id="root" style="font:15px system-ui"></div>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
<script type="text/babel" data-type="module">
import React from 'https://esm.sh/react@19.3.0';
import { createRoot } from 'https://esm.sh/react-dom@19.3.0/client';
function Row({ label, items }) {
  if (!items) return null;                        // 1. early return
  let tag;                                        // 2. if before the return
  if (items.length > 3) tag = <b> (many)</b>;
  return (                                        // 3. ternary   4. &&
    <li>{label}: {items.length ? items.join(', ') : <i>empty</i>}{tag}
      <br />broken: {items.length && ' in stock'}
      <br />fixed:  {items.length > 0 && ' in stock'}</li>
  );
}
const lists = { Keyboards: ['K1', 'K2', 'K3', 'K4'], Monitors: [], Cables: null };
createRoot(document.getElementById('root')).render(
  <ul>{Object.entries(lists).map(([k, v]) => <Row key={k} label={k} items={v} />)}</ul>
);
</script>
Browser output of Listing 2.7
Browser output of 7

Cables disappears entirely: its component returned null. Monitors shows the bug — a literal 0 where nothing should appear — while the "fixed" line stays blank. Keep conditions shallow: nested ternaries inside JSX become unreadable past the second level, and the cure is to pull the branch into its own component.