在React开发中,条件渲染是我们经常使用的一项重要技术。它允许我们根据特定条件决定是否渲染某段JSX代码或整个组件。今天,紧接着上一小节的代码,我将详细探讨如何使用”&”运算符实现条件渲染,并分享一些使用过程中的注意事项。
初始代码(点击显示)
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() {
return (
<main className="menu">
<h2>Our Menu</h2>
<ul className="pizzas">
{pizzaData.map((pizza) => (
<Pizza pizzaObj={pizza} key={pizza.name}/>
))}
</ul>
{/* <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 = 12;
const closeHour = 22;
const isOpen = hour >= openHour && hour <= closeHour;
console.log(isOpen);
return (
<footer className="footer">
{new Date().toLocaleDateString()}. We're currently open.
</footer>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
什么是条件渲染?
条件渲染简单来说就是基于某个条件决定是否显示UI的某个部分。这个条件可以是任何返回true或false的表达式。在实际应用中,这种技术非常有用,比如:
- 只在餐厅营业时显示”下单”按钮
- 只在有数据时显示列表
- 只对登录用户显示某些功能
使用 && 运算符进行条件渲染
在React中使用 && 运算符进行条件渲染利用了JavaScript的”短路求值”(short-circuiting)特性。
基本原理
当我们使用表达式 condition && expression 时:
- 如果condition为真(truthy),则返回expression
- 如果condition为假(falsy),则直接返回condition,不会执行expression
实际示例:
我们修改Footer组件里面如下代码⬇️
{isOpen && <p>We're open until {closeHour}. Come visit us or order online.</p>}在这个例子中:
- 当isOpen为true时,段落内容会被渲染
- 当isOpen为false时,React不会渲染任何内容(因为React不会渲染布尔值)
需要注意的陷阱
使用 &&运算符进行条件渲染时有一个常见陷阱需要注意。让我们通过一个例子来说明:
在menu组件中假设我们想在有披萨数据时才渲染披萨列表:
{pizzas && <ul>{pizzas.map(...)}</ul>}这段代码看起来没问题,但有一个潜在问题:
- 当pizzas是空数组时,它仍然是一个truthy值!
- 因此即使没有披萨数据,
<ul></ul>仍然会被渲染
更好的方法是检查数组的长度:
{pizzas.length && <ul>{pizzas.map(...)}</ul>}但这里又有一个问题:
- 当pizzas.length为0时,& 运算符会返回0
- React会将0渲染到UI中
正确的做法应该是使用布尔表达式:
{pizzas.length > 0 && <ul>{pizzas.map(...)}</ul>}&& 运算符的优缺点
优点
- 语法简洁
- 对于简单条件渲染很方便
缺点
- 容易出现上述陷阱
- 没有”else”分支处理
- 如果条件是数字0,可能会意外渲染0
结论
虽然有些开发者认为不应该使用 && 运算符进行条件渲染,但我认为在特定场景下它仍然是一个有用的工具。不过,对于大多数条件渲染场景,三元运算符(条件 ? 表达式1 : 表达式2)可能是更安全、更灵活的选择。
完整代码(点击显示)
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>
) }
{/* <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>)}
</footer>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

发表回复