cf.completefrontend
Open lab My progress
THE REACT FIELD GUIDE

Conditional rendering

Show different UI for different data in React: if and early returns, the ternary, && without the stray 0, and returning null, in live examples you can edit.

By the end, you can
  • 01
    Choose with if and early returnsReturn different JSX for different data, and handle a special case, like an empty cart, first with an early return.
  • 02
    Pick parts inside the JSXUse the ternary to choose one of two pieces and && to show a piece or nothing, without the stray 0 a number can leave.
  • 03
    Decide where a condition livesSay what changes when a parent leaves a component out, when the component returns null, and when an element is only hidden.

One component, a different row for each case

Real pages change with their data. A product that's sold out shows "sold out" instead of a button. An empty cart says so. A sale banner appears only during a sale. Showing different things in different cases is called conditional rendering, and React has no special syntax for it: you use the JavaScript you already know. Here is a product list where one row is different. Its result is live under the code.

A product row that knows when it's sold outPop out in the code editor (opens in a new tab)JSX
function ProductRow({ name, stock }) {  if (stock === 0) {    return <li>{name}: sold out</li>;  }  return (    <li>      {name}: {stock} left <button>Add to cart</button>    </li>  );} export default function App() {  return (    <ul>      <ProductRow name="Tea" stock={5} />      <ProductRow name="Cake" stock={2} />      <ProductRow name="Lemonade" stock={0} />    </ul>  );}
ResultLoading…

ProductRow on line 1 takes two props, name and stock, from its tag on lines 15 to 17, as in Passing props to a component.

Line 2 is a plain if statement. When stock is 0, line 3 returns a short row that says sold out, and the function ends there. Otherwise the if is skipped, and lines 5 to 9 return the full row with the count and a button. App uses ProductRow three times, so the result shows Tea: 5 left and Cake: 2 left, each with a button, and Lemonade: sold out.

Press Edit & run and change Lemonade's stock={0} on line 17 to stock={3}. The result updates as you type: Lemonade gets 3 left and a button. You changed the data; the component chose the row.

A card, stock={0}, goes into a function card, ProductRow. Two arrows leave it. The top one leads to the card li Lemonade: sold out, labelled yes, line 3 returns this. The bottom one leads to a faded, crossed-out card, li with a button, labelled lines 5 to 9 never run.stock={0}Lemonade's propsProductRow()stock === 0 ?<li>…sold out</li>yes: line 3 returns this<li>…<button>…</li>lines 5 to 9 never run
For Lemonade, stock is 0, so the if on line 2 is true and line 3 returns the sold-out row. For Tea and Cake it's false, and the return on lines 5 to 9 runs instead. One function, two possible rows.
Real-life analogyA café's chalkboard

A café's chalkboard lists today's cakes. The owner looks in the kitchen and writes the board to match: a price for the cakes she has, "sold out" for the ones that are gone, and no line at all for the cakes she doesn't make today. She follows the same rules every time; only the kitchen changes.

In real life: What's left in the kitchen right now
In React: The props and data, like stock
In real life: The rule: if a cake is gone, write "sold out"
In React: if (stock === 0) return <li>…sold out</li>;
In real life: Writing the board for what's true now
In React: Your component returning JSX for the current data
In real life: Leaving a line off the board
In React: Returning null, or false from &&, so React shows nothing there
The main idea

Conditional rendering means choosing what a component returns with ordinary JavaScript: an if before the return, or the ternary ? : and && inside the JSX. Whatever the component returns for the current data is what React shows. When it returns null, or a spot in the JSX holds false, React shows nothing there.

Choosing with if, before the return

A component is a function, so everything a function can do before its return is open to you, including if. The most common shape is the early return: handle a special case first and return right away, so the rest of the function only deals with the usual case. A cart summary is a good fit, because an empty cart has nothing to add up:

An empty cart returns earlyPop out in the code editor (opens in a new tab)JSX
function CartSummary({ items }) {  if (items.length === 0) {    return <p>Your cart is empty.</p>;  }   const total = items.reduce((sum, item) => sum + item.price, 0);  return (    <p>      {items.length} items, ${total} in total    </p>  );} const tea = { name: "Tea", price: 3 };const cake = { name: "Cake", price: 4 }; export default function App() {  return (    <>      <CartSummary items={[]} />      <CartSummary items={[tea, cake]} />    </>  );}
ResultLoading…

Line 2 checks for an empty cart. If items has no items, line 3 returns Your cart is empty. and CartSummary stops: a return ends the function, so line 6 never runs. For a cart with items, line 6 adds up the prices with reduce, and lines 7 to 11 return the summary. Line 20 passes an empty array and line 21 passes tea and cake, so the result shows Your cart is empty., then 2 items, $7 in total.

The if sits above the return, not inside the JSX. As JavaScript in JSX with curly braces showed, curly braces take only an expression, code that gives back a value, and if is a statement. Inside the braces, the ternary and && below do the choosing.

An if can also choose what goes in one part of the markup. JSX is a value, a small object that describes an element, so you can store it in a variable, change it with if, and put the variable in the braces:

An order status chosen with if and a variablePop out in the code editor (opens in a new tab)JSX
function OrderStatus({ id, status }) {  let message = <span>We're packing it.</span>;  if (status === "shipped") {    message = <span>It's on its way.</span>;  } else if (status === "delivered") {    message = <strong>Delivered.</strong>;  }  return <li>Order {id}: {message}</li>;} export default function App() {  return (    <ul>      <OrderStatus id={7} status="packing" />      <OrderStatus id={8} status="shipped" />      <OrderStatus id={9} status="delivered" />    </ul>  );}
ResultLoading…

Line 2 makes message with the usual case, a <span> saying We're packing it. It uses let, so lines 4 and 6 can replace it: with "on its way" when the order has shipped, or a <strong> when it's delivered. Line 8 puts whichever one is left into the row with {message}. The result shows three orders, 7, 8, and 9, one in each state.

This is the most flexible shape, and the one to reach for when there are three or more cases, or when each case needs a few lines of its own. The <li> around the message is written once, on line 8, whatever the status.

The ternary: one of two, inside the JSX

The overview's ProductRow has two return statements, and both build an <li>. When only a small part changes, you can write the row once and choose just that part with the ternary operator: condition ? a : b gives back a when the condition is true and b when it's false. It's an expression, so it fits inside curly braces, and in an attribute's value too:

One row with two ternariesPop out in the code editor (opens in a new tab)JSX
function ProductRow({ name, stock }) {  return (    <li className={stock > 0 ? "in-stock" : "sold-out"}>      {name}: {stock > 0 ? <button>Add to cart</button> : <em>sold out</em>}    </li>  );} export default function App() {  return (    <ul>      <ProductRow name="Tea" stock={5} />      <ProductRow name="Cake" stock={2} />      <ProductRow name="Lemonade" stock={0} />    </ul>  );}
ResultLoading…

Line 3 picks the row's class: "in-stock" when stock > 0, otherwise "sold-out". The styles.css tab makes in-stock rows bold and fades sold-out ones. Line 4 picks the end of the row: a button, or <em>sold out</em>. Read it as "if stock > 0, a button, otherwise sold out". Tea and Cake get buttons, and Lemonade's row is faded and says sold out.

Is this different from writing two returns? No. JSX elements are descriptions, not pieces of the page, so both versions hand React the same description for the same data, and the page ends up the same. Choose whichever reads better: two returns when the cases are very different, a ternary when they share most of the markup.

A ternary inside another ternary works, but it gets hard to read quickly:

A ternary inside a ternaryJSX
<p>
  {stock === 0 ? "Sold out" : stock < 3 ? "Only a few left" : "In stock"}
</p>

Line 2 reads: if stock is 0, Sold out; otherwise, if it's below 3, Only a few left; otherwise In stock. It's a fragment of a component, so it has no result of its own. The same three cases read more easily as if statements with a variable, before the return:

Three cases with if and a variablePop out in the code editor (opens in a new tab)JSX
function StockLabel({ stock }) {  let label = "In stock";  if (stock === 0) {    label = "Sold out";  } else if (stock < 3) {    label = "Only a few left";  }  return <p>{label}</p>;} export default function App() {  return (    <>      <StockLabel stock={5} />      <StockLabel stock={2} />      <StockLabel stock={0} />    </>  );}
ResultLoading…

Line 2 starts with the usual case, and lines 3 to 7 replace it for the two special ones. Line 8 shows the result. For stock 5, 2, and 0, the result reads In stock, Only a few left, and Sold out.

&& for something or nothing, and the stray 0

Often you want a piece of markup in one case and nothing in the other: a note for members, a free-delivery line over $20. A ternary with null on one side works, and && says it more briefly:

Delivery notes with &&Pop out in the code editor (opens in a new tab)JSX
function Checkout({ total, isMember }) {  return (    <section>      <p>Total: ${total}</p>      {isMember && <p>Members get free delivery.</p>}      {total >= 20 && <p>Your order ships free.</p>}    </section>  );} export default function App() {  return (    <>      <Checkout total={12} isMember={true} />      <Checkout total={25} isMember={false} />    </>  );}
ResultLoading…

Read line 5 as "if isMember, then this paragraph". Here is how it works. a && b looks at a first. If a is falsy, it stops and gives back a itself. If a is truthy, it gives back b. So for a member, line 5 gives back the <p>; for anyone else it gives back false. React draws nothing for false, true, null, or undefined, so that spot stays empty. Line 6 does the same with a comparison: total >= 20.

Line 14 is a member with a $12 order, and line 15 isn't a member but spends $25. The result shows Members get free delivery. under the first total and Your order ships free. under the second.

There's one trap. "Gives back a itself" matters when a is a number, because React does show numbers, including 0. Here a cart link shows its count in brackets, with a bug on purpose:

A cart link with a stray 0 (a bug on purpose)Pop out in the code editor (opens in a new tab)JSX
function CartLink({ count }) {  return (    <p>      Cart {count && <strong>({count})</strong>}    </p>  );} export default function App() {  return (    <>      <CartLink count={2} />      <CartLink count={0} />    </>  );}
ResultLoading…

The first link says Cart (2), as it should. The second says Cart 0. On line 4, count && … with a count of 0 stops at the falsy 0 and gives back 0, not false, and React shows it. NaN, the "not a number" value, does the same. An empty string "" is given back too, but it shows as empty text, so you can't see it.

Three rows. Row one: count = 2, the && gives back the strong element, and the page shows Cart (2). Row two: count = 0, the && gives back 0, and the page shows Cart 0, a stray 0. Row three: count > 0 with count 0, the && gives back false, and the page shows Cart with nothing extra.left sidewhat && gives backon the pagecount = 2<strong>(2)</strong>Cart (2)count = 00Cart 0a stray 0count > 0falseCartnothing extrawith count = 0
&& gives back its left side when that side is falsy. For 0, that's the number 0, and React shows numbers. Compare first: 0 > 0 is false, and React draws nothing for false.

The fix is to give && a true-or-false test. Press Edit & run and change line 4 to {count > 0 && <strong>({count})</strong>}. 0 > 0 is false, so the second link reads just Cart. A ternary, {count > 0 ? <strong>…</strong> : null}, works too. The JavaScript you need for React has a playground that shows what JSX does with every kind of value.

The cart link, fixed with a comparisonPop out in the code editor (opens in a new tab)JSX
function CartLink({ count }) {  return (    <p>      Cart {count > 0 && <strong>({count})</strong>}    </p>  );} export default function App() {  return (    <>      <CartLink count={2} />      <CartLink count={0} />    </>  );}
ResultLoading…

Returning null, and where the condition lives

A component can return null, which means "nothing to show". So a component can decide for itself to show nothing. Here a sale banner returns null when there's no sale:

A sale banner that returns nullPop out in the code editor (opens in a new tab)JSX
function SaleBanner({ onSale }) {  if (!onSale) {    return null;  }  return <p className="banner">Sale: 20% off tea</p>;} function ProductPage({ onSale }) {  return (    <div>      <h3>Green tea</h3>      <SaleBanner onSale={onSale} />      <p>$3</p>    </div>  );} export default function App() {  return (    <>      <ProductPage onSale={true} />      <ProductPage onSale={false} />    </>  );}
ResultLoading…

Lines 2 to 4 return null when onSale is false, so SaleBanner shows nothing. Otherwise line 5 returns the banner. Line 12 uses SaleBanner inside ProductPage and passes onSale along. Lines 21 and 22 show the page twice: the first with the banner under the heading, the second without it.

The same page could leave the banner out from the parent instead: {onSale && <SaleBanner />} in ProductPage, with a SaleBanner that always shows. The page looks the same. What differs is what React gets. Try all four ways below; onSale switches the sale on and off, and the result pane shows what ProductPage returns, whether React calls SaleBanner, and the real HTML on the page.

Playground: where does the condition live?
ProductPage and SaleBanner: && in ProductPageJSX
function SaleBanner() {  return <p className="banner">Sale: 20% off tea</p>;} function ProductPage({ onSale }) {  return (    <div>      <h3>Green tea</h3>      {onSale && <SaleBanner />}      <p>$3</p>    </div>  );}
What React gets and showsonSale={false}
Try it yourself
&& in ProductPage, onSale = false

false && … gives back false, so ProductPage's description holds false where the banner was. React draws nothing for it and never calls SaleBanner.

The code runs for real: this page compiles it with Sucrase, the compiler the live examples use, and React renders ProductPage into the result. The list comes from calling ProductPage with your onSale, and the HTML is read from the page after React's update.

Start with && in ProductPage and onSale={false}. The <div> holds <h3>, false, and <p>, and SaleBanner is "Not called": React calls only the components in the description. Pick SaleBanner returns null: the description now holds <SaleBanner onSale={false} />, so React calls it, and it returns null. The HTML is the same both times.

Two trees side by side. Left, with onSale && SaleBanner in ProductPage: ProductPage has three children, h3, a faded crossed-out false, and p; SaleBanner is never called. Right, with SaleBanner returning null: ProductPage has three children, h3, the function SaleBanner, and p; an arrow leads from SaleBanner down to a card, null.{onSale && <SaleBanner />}ProductPage<h3>false<p>SaleBanner isnever calledif (!onSale) return null;ProductPage<h3>SaleBanner<p>nullReact calls it; it returns null
With onSale false, both pages look the same. On the left, ProductPage's description holds false, and React never calls SaleBanner. On the right, it holds a <SaleBanner>, so React calls it, and it returns null.

Which to choose? Usually the parent: {onSale && <SaleBanner />} says right where the banner is used that it might not show. Returning null suits a component that knows better than its parents when it has nothing to say, like a warning that checks its own numbers. Either way, prefer null to undefined. Since React 18, a component that returns undefined also shows nothing, without an error, so a forgotten return fails silently; return null says you meant it.

Not rendered means removed

Now pick the hidden attribute with onSale={false}. The HTML still holds the banner's <p>, with hidden: it's on the page, and the browser doesn't draw it. With the other three ways, the element isn't there at all. That difference matters as soon as the element holds something the reader typed:

A gift note that disappears with its textPop out in the code editor (opens in a new tab)JSX
import { useState } from "react"; export default function App() {  const [wantsNote, setWantsNote] = useState(false);   return (    <>      <label>        <input          type="checkbox"          checked={wantsNote}          onChange={(event) => setWantsNote(event.target.checked)}        />        Add a gift note      </label>      {wantsNote && <textarea placeholder="Your note" />}    </>  );}
ResultLoading…

Line 4 keeps wantsNote in state, a value React remembers for the component, starting as false. Ticking the box on lines 9 to 13 sets it, and React shows the component again (state gets its own lesson, State: a component's memory). Line 16 shows the <textarea> only while wantsNote is true.

Tick the box, type Happy birthday, Asha, untick it, and tick it again. The box is empty. When wantsNote became false, React removed the <textarea> from the page, and your text went with it; ticking again made a new, empty one. Now press Edit & run and change line 16 to <textarea placeholder="Your note" hidden={!wantsNote} />. Try again: the note is still there, because the element never left the page. Remove what you don't need; hide what has to keep its contents.

An order history with every kind of condition

A real page mixes all of these. Here is an order history: each order shows its status, a gift label when it's a gift, and a button that depends on where the order is.

const orders = [  { id: 7, item: "Tea", status: "delivered", gift: false },  { id: 8, item: "Cake", status: "shipped", gift: true },  { id: 9, item: "Lemonade", status: "packing", gift: false },]; function OrderActions({ status }) {  if (status === "packing") {    return <button>Cancel</button>;  }  if (status === "shipped") {    return <button>Track</button>;  }  return null;} function OrderRow({ order }) {  const done = order.status === "delivered";  return (    <li>      #{order.id} {order.item}: {done ? <strong>delivered</strong> : order.status}      {order.gift && <em> (gift)</em>} <OrderActions status={order.status} />    </li>  );} export default function App() {  if (orders.length === 0) {    return <p>No orders yet.</p>;  }  return (    <ul>      {orders.map((order) => (        <OrderRow key={order.id} order={order} />      ))}    </ul>  );}
ResultLoading…

Each kind of condition has a job:

  • Lines 28 to 30 are an early return in App: with no orders, the page says No orders yet. and stops.
  • Lines 7 to 15 are OrderActions, which decides for itself: a Cancel button while packing, Track once shipped, and null after delivery, when there's nothing to do.
  • Line 21's ternary bolds delivered and shows the other statuses as they are. Line 22's && adds (gift) only when order.gift is true; it's a true-or-false value, so no stray 0.

The result shows #7 Tea: delivered with no button, #8 Cake: shipped (gift) with Track, and #9 Lemonade: packing with Cancel. Press Edit & run and replace lines 1 to 5 with const orders = [];. The result shows No orders yet. Lines 33 to 35 turn the array into rows with map and give each a key; the next lesson, Rendering lists, is all about that.

How to read this table: each row is something you want the page to do, what to write, and why it works.

Which condition to use
You wantWriteWhy
A different screen for a special case, like an empty cartif (items.length === 0) return <p>…</p>;The early return handles the case first, so the rest of the function only deals with the usual case.
One of two pieces inside the markup{inStock ? <button>…</button> : <em>sold out</em>}The ternary is an expression, so it fits in curly braces, and both pieces share the markup around them.
A piece or nothing{isMember && <p>…</p>}With true or false on the left, && gives back the element or false, and React draws nothing for false.
A piece or nothing, based on a number{count > 0 && <strong>…</strong>}The comparison turns the number into true or false, so a 0 can't reach the page.
Three or more casesif and else if that set a variable before the returnA ternary inside a ternary is hard to read. Plain if statements stay clear.
A component that decides for itselfif (!onSale) return null;React still calls the component, and draws nothing for null.
Out of sight, but keep what was typedhidden={!wantsNote}The element stays on the page, only hidden, so the text in it stays too.
Element or a stray value?
  • {count && <Badge />}, where count is a number
  • {count > 0 && <Badge />}, where count is a number
  • {items.length && <List />}, where items is an array
  • {items.length > 0 && <List />}, where items is an array
  • {user && <Greeting />}, where user is an object or null
  • {price && <Price />}, where price is a number, and can be NaN
  • {count ? <Badge /> : null}, where count is a number
  • {name && <Greeting />}, where name is a string
Try it yourself
0 of 8 correct

Each card is an expression in JSX braces, with what its variable holds. Sort it: does it show only the element or nothing, or can it show a stray 0 or NaN?

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Common mix-ups

  • "React has a special tag for conditions." No. Some other libraries have one, like Vue's v-if. React uses plain JavaScript: if, ? :, and &&.
  • "A component must always return some JSX." No. It can return null to show nothing, as SaleBanner and OrderActions do.
  • "When the left side of && is false, nothing shows." Only when it's false, null, undefined, or an empty string. A 0 or NaN shows. Compare first: count > 0 && ….
  • "A component that returns null is skipped." No. React still calls it; it just shows nothing. To keep React from calling it, leave it out in the parent.
  • "Conditional rendering hides an element." No. It removes the element from the page, with anything typed into it. To keep it and only hide it, use the hidden attribute or CSS.
  • "Two returns make different elements than one return with a ternary." No. JSX describes elements; for the same data both versions describe the same thing, and the page ends up the same.

Practice exercises

Each exercise shows its result under the code, or when you press Edit & run. Change the code, and the result updates as you type. For the first two, answer before you run anything.

Exercise 1 · Warm-upPredict the empty inbox

What shows under the Inbox heading? Answer first, then press Edit & run to check.

function Inbox({ messages }) {
  return (
    <section>
      <h3>Inbox</h3>
      {messages.length && <p>You have {messages.length} new messages.</p>}
    </section>
  );
}

export default function App() {
  return <Inbox messages={[]} />;
}

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upPredict the greeting

    What does the page say for a visitor who isn't signed in?

    function Greeting({ user }) {
      if (!user) {
        return <p>Sign in to see your orders.</p>;
      }
      return <p>Welcome back, {user.name}!</p>;
    }
    
    export default function App() {
      return <Greeting user={null} />;
    }

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFix the stray 0

      The second link says Cart 0. Fix line 4 so an empty cart shows no number. What does the second line say then?

      function CartLink({ count }) {  return (    <p>      Cart {count && <strong>({count})</strong>}    </p>  );} export default function App() {  return (    <>      <CartLink count={2} />      <CartLink count={0} />    </>  );}
      ResultLoading…

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeOne return with a ternary

        Rewrite Delivery with a single return, so the <li> is written once. Keep the result the same. How many return statements does Delivery have now?

        function Delivery({ name, express }) {  if (express) {    return <li>{name}: arrives tomorrow</li>;  }  return <li>{name}: arrives in 3 days</li>;} export default function App() {  return (    <ul>      <Delivery name="Tea" express={true} />      <Delivery name="Cake" express={false} />    </ul>  );}
        ResultLoading…

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeA warning that hides itself

          Write a LowStockWarning component that shows a warning like Only 2 left! when there are 1 or 2 left, and nothing otherwise, even for sold-out products. Use it in every ProductCard. How many warnings show?

          // Write LowStockWarning here. function ProductCard({ name, stock }) {  return (    <li>      {name}    </li>  );} export default function App() {  return (    <ul>      <ProductCard name="Tea" stock={5} />      <ProductCard name="Cake" stock={2} />      <ProductCard name="Lemonade" stock={0} />    </ul>  );}
          ResultLoading…

          Answer, then press Check. Spacing and letter case don’t matter.

            Exercise 6 · ChallengeLoading, empty, and full

            reviews is null while the reviews load, and [] when there are none. Make ReviewList show Loading reviews… and No reviews yet. for those cases. What does the second ReviewList show?

            function ReviewList({ reviews }) {  // reviews is null while loading, [] when there are none.  return <p>{reviews?.length} reviews</p>;} export default function App() {  return (    <>      <ReviewList reviews={null} />      <ReviewList reviews={[]} />      <ReviewList reviews={["Lovely tea", "Fresh cake"]} />    </>  );}
            ResultLoading…

            Answer, then press Check. Spacing and letter case don’t matter.

              Check your understanding

              For each code question, find the data first, then follow the condition. Press Edit & run on a question's code to check your answer.

              The conditional rendering quiz · 7 questionsScore: first tries count
              1. Question 1 of 7What does this component show for unread={0}?

                Read the code, then predictPop out in the code editor (opens in a new tab)JSX
                function Messages({ unread }) {
                  return <p>Messages {unread && <b>({unread})</b>}</p>;
                }
                
                export default function App() {
                  return <Messages unread={0} />;
                }

                Choose an answer to see the explanation.

              2. Question 2 of 7A label has three cases: sold out, only a few left, and in stock. Which way does this lesson suggest?

                Choose an answer to see the explanation.

              3. Question 3 of 7What does Shipping show for status="shipped"?

                Read the code, then predictPop out in the code editor (opens in a new tab)JSX
                function Shipping({ status }) {
                  if (status === "lost") {
                    return <p>Please contact us.</p>;
                  }
                  if (status === "shipped") {
                    return <p>On its way.</p>;
                  }
                  return <p>Packing.</p>;
                }
                
                export default function App() {
                  return <Shipping status="shipped" />;
                }

                Choose an answer to see the explanation.

              4. Question 4 of 7What class does Lemonade's <li> get?

                Read the code, then predictPop out in the code editor (opens in a new tab)JSX
                function ProductRow({ name, stock }) {
                  return <li className={stock > 0 ? "in-stock" : "sold-out"}>{name}</li>;
                }
                
                export default function App() {
                  return (
                    <ul>
                      <ProductRow name="Lemonade" stock={0} />
                    </ul>
                  );
                }

                Choose an answer to see the explanation.

              5. Question 5 of 7ProductPage writes {onSale && <SaleBanner />}, and onSale is false. What does React do with SaleBanner?

                Choose an answer to see the explanation.

              6. Question 6 of 7In the gift note example, you tick the box, type a note, untick it, and tick it again. What's in the box?

                Choose an answer to see the explanation.

              7. Question 7 of 7You want a badge only when items.length is above 0. Which line is safe?

                Choose an answer to see the explanation.

              Key takeaways

              • React has no special syntax for conditions. A component chooses what to return with plain JavaScript.
              • Use if before the return for whole different results, and early returns for special cases like an empty cart.
              • Inside the JSX, a ? b : c picks one of two pieces, and a && b shows a piece or nothing. Give && a true-or-false test, like count > 0, or a 0 shows up.
              • React shows nothing for null, false, true, and undefined. A component can return null, but React still calls it; leaving it out in the parent means React never does.
              • A condition that turns false removes the element from the page, with anything typed into it. The hidden attribute only hides it.

              Remember the one-liner.
              The component decides with plain JavaScript; React shows whatever it returns, and nothing for null and false.

              Coming next: Rendering lists. It turns arrays of data into lists of components with map and filter, and shows why each item needs a key.

              CompleteFrontend Clear concepts. Working examples.