19. React条件渲染深度解析:多重返回值技巧详解

初始代码(点击展开)
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";

const pizzaData = [
  {
    name: "Focaccia",
    ingredients: "Bread with italian olive oil and rosemary",
    price: 6,
    photoName: "pizzas/focaccia.jpg",
    soldOut: false,
  },
  {
    name: "Pizza Margherita",
    ingredients: "Tomato and mozarella",
    price: 10,
    photoName: "pizzas/margherita.jpg",
    soldOut: false,
  },
  {
    name: "Pizza Spinaci",
    ingredients: "Tomato, mozarella, spinach, and ricotta cheese",
    price: 12,
    photoName: "pizzas/spinaci.jpg",
    soldOut: false,
  },
  {
    name: "Pizza Funghi",
    ingredients: "Tomato, mozarella, mushrooms, and onion",
    price: 12,
    photoName: "pizzas/funghi.jpg",
    soldOut: false,
  },
  {
    name: "Pizza Salamino",
    ingredients: "Tomato, mozarella, and pepperoni",
    price: 15,
    photoName: "pizzas/salamino.jpg",
    soldOut: true,
  },
  {
    name: "Pizza Prosciutto",
    ingredients: "Tomato, mozarella, ham, aragula, and burrata cheese",
    price: 18,
    photoName: "pizzas/prosciutto.jpg",
    soldOut: false,
  },
];

function App() {
  return (
    <div className="container">
      <Header />
      <Menu />
      <Footer />
    </div>
  );
}

function Header() {
  const style = {};

  return (
    <header className="header">
      <h1 style={style}>Fast React Pizza Co.</h1>
    </header>
  );
}

function Menu() {
  const pizzas = pizzaData;

  // const pizzas = [];

  const numPizzas = pizzas.length;

  return (
    <main className="menu">
      <h2>Our Menu</h2>

      {numPizzas > 0 ? (
        <ul className="pizzas">
          {pizzas.map((pizza) => (
            <Pizza pizzaObj={pizza} key={pizza.name} />
          ))}
        </ul>
      ) : (
        <p>We're still working on our menu. Please come back later</p>
      )}

      {/* <Pizza
        name="Pizza Spinaci"
        ingredient="Tomato, mozarella, spinach, and ricotta cheese"
        photoName="pizzas/spinaci.jpg"
        price={10}
      />
      <Pizza
        name="Pizza Funghi"
        ingredient="Tomato, mushrooms"
        price={12}
        photoName="pizzas/funghi.jpg"
      /> */}
    </main>
  );
}

function Pizza(props) {
  console.log(props);
  return (
    <li className="pizza">
      <img src={props.pizzaObj.photoName} alt={props.pizzaObj.name}></img>
      <div>
        <h3>{props.pizzaObj.name}</h3>
        <p>{props.pizzaObj.ingredients}</p>
        <span>{props.pizzaObj.price}</span>
      </div>
    </li>
  );
}

function Footer() {
  const hour = new Date().getHours();
  const openHour = 20;
  const closeHour = 22;
  const isOpen = hour >= openHour && hour <= closeHour;

  console.log(isOpen);

  return (
    <footer className="footer">
      {isOpen ? (
        <div className="order">
          <p>We're open until {closeHour}:00. Come visit us or order online.</p>
          <button className="btn">Order</button>
        </div>
      ) : (
        <p>
          We're happy to welcome you between {openHour}:00 and {closeHour}
        </p>
      )}
    </footer>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

React中条件渲染是一项基础但强大的技术,它允许我们根据不同的状态或条件显示不同的UI。在之前的学习中,我们已经了解了使用三元运算符和逻辑与运算符的条件渲染方法。今天,我们将深入探讨第三种条件渲染方式:多重返回值。

多重返回值:基本概念

到目前为止,我们的组件都只有一个返回语句,但实际上React组件可以根据条件返回不同的JSX内容。尽管每个组件最终只能返回一个JSX块,但这个返回值可以基于条件来决定。

在组件函数中,JSX外部的区域是纯JavaScript环境,我们可以在这里使用标准的if语句进行条件判断,并在满足特定条件时提前返回不同的JSX内容。

实际应用示例

示例1:根据营业状态显示信息

让我们看看如何在Footer组件中使用多重返回:

function Footer() {
  const hour = new Date().getHours();
  const openHour = 20;
  const closeHour = 22;
  const isOpen = hour >= openHour && hour <= closeHour;

  console.log(isOpen);

  if (!isOpen)
    return (
      <p>
        We're happy to welcome you between {openHour}:00 and {closeHour}
      </p>
    );

  return (
    <footer className="footer">
      {isOpen ? (
        <div className="order">
          <p>We're open until {closeHour}:00. Come visit us or order online.</p>
          <button className="btn">Order</button>
        </div>
      ) : (
        <p>
          We're happy to welcome you between {openHour}:00 and {closeHour}
        </p>
      )}
    </footer>
  );
}

这段代码中,如果餐厅未营业,我们会直接返回一条信息。但需要注意,这样做会导致footer元素在餐厅未营业时不被渲染,这可能不是我们想要的效果。如果希望保持一致的DOM结构,我们需要在两种情况下都包含footer元素。

示例2:有条件地渲染组件

多重返回值在决定是否渲染整个组件时特别有用。例如,在我们的Pizza组件中:

每个披萨对象有一个属性soldOut

  • 当soldOut为true时,表示该披萨已售罄
  • 当soldOut为false时,表示该披萨还有库存
function Pizza(props) {
  // 如果披萨售罄,不渲染任何内容
  if (props.pizzaObj.soldOut) {
    return null;
  }
  
  return (
    <li className="pizza">
      <img src={props.pizzaObj.photoName} alt={props.pizzaObj.name}></img>
      <div>
        <h3>{props.pizzaObj.name}</h3>
        <p>{props.pizzaObj.ingredients}</p>
        <span>{props.pizzaObj.price}</span>
      </div>
    </li>
  );
}

通过这个简单的条件判断,售罄的披萨(如Pizza Salamino)将不会在菜单中显示。这是一种常见且实用的技巧,即在某些条件下返回null,从而不在DOM中渲染任何内容。

条件渲染方法的选择

结合之前讲解,我们已经学习了三种条件渲染的方法:

  1. 三元运算符 ? :
  2. 逻辑与运算符 &&
  3. 多重返回值

每种方法都有其适用场景:

  • 当需要基于条件在JSX中渲染不同内容时,三元运算符最为常用
  • 当需要决定是否渲染整个组件或返回完全不同的内容时,多重返回值是理想选择
  • 对于简单的”渲染或不渲染”逻辑,逻辑与运算符&&简洁明了


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注