在 React 中,我们经常需要根据不同的状态展示不同的界面,这就是条件渲染。React 不提供专用的条件渲染指令(如 Vue 的 v-if),而是直接利用 JavaScript 的表达式能力在 JSX 中实现。掌握好条件渲染,是写出灵活、可读组件的基础。
3.4.1 三元运算符(condition ? A : B)
三元运算符是最常用的条件渲染方式,适用于“二选一”的场景:当条件为真时显示组件 A,否则显示组件 B。
function Greeting({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? <UserDashboard /> : <LoginButton />}
</div>
);
}
三元运算符可以内联在 JSX 的任何地方,清晰表达条件与结果的关系。如果条件逻辑较复杂,建议提前计算好条件变量,避免在 JSX 中写过长表达式:
const buttonText = isLoading ? '加载中...' : '提交';
return <button disabled={isLoading}>{buttonText}</button>;
3.4.2 逻辑与运算符(condition && <Component />)
当只需要在条件为真时渲染某内容,为假时不渲染任何内容时,可以使用 && 运算符。它利用了 JavaScript 的短路特性:如果左侧表达式为真,则返回右侧的 JSX;如果为假,则返回左侧的值(React 不会渲染 false、null、undefined)。
function Notification({ hasNewMessage }) {
return (
<div>
<h1>消息列表</h1>
{hasNewMessage && <span className="badge">新消息</span>}
</div>
);
}
这种方式简洁直观,但需要警惕左侧值为数字 0 或 NaN 时的情况。React 会渲染数字 0,可能导致界面上出现意外的“0”。例如:
{items.length && <p>共有 {items.length} 条记录</p>}
当 items.length 为 0 时,条件判断为假,但 0 本身会被 React 渲染。为了避免这个问题,应该显式转换为布尔值:
{items.length > 0 && <p>共有 {items.length} 条记录</p>}
3.4.3 条件返回(提前返回)
如果组件的逻辑分支较多,或者“不满足条件时整个组件不渲染”,可以在函数组件中使用 if 语句进行提前返回。这可以让代码结构更清晰,避免深层的 JSX 嵌套。
function UserProfile({ user, isLoading, error }) {
if (isLoading) {
return <Spinner />;
}
if (error) {
return <ErrorMessage message={error} />;
}
if (!user) {
return null; // 什么都不渲染
}
return (
<div className="profile">
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
上面的例子中,每种状态都是一条独立的路径,阅读时一目了然。对于复杂组件来说,这种“守卫式”提前返回是值得推荐的做法。
3.4.4 更复杂的分支:使用变量或函数
当分支超过两条时,不要强行在 JSX 中嵌套三元运算,这会严重影响可读性。更好的做法是使用变量或辅助函数来缓存 JSX 片段。
使用变量:
function StatusCard({ status }) {
let content;
if (status === 'loading') {
content = <Spinner />;
} else if (status === 'error') {
content = <ErrorMessage />;
} else if (status === 'empty') {
content = <EmptyState />;
} else {
content = <DataView />;
}
return <div className="card">{content}</div>;
}
使用函数(或组件内辅助方法):
function StatusCard({ status }) {
const renderContent = () => {
switch (status) {
case 'loading': return <Spinner />;
case 'error': return <ErrorMessage />;
case 'empty': return <EmptyState />;
default: return <DataView />;
}
};
return <div className="card">{renderContent()}</div>;
}
这两种方式都把条件逻辑从 JSX 中抽离至 JavaScript 逻辑区域,保持了 JSX 的简洁性。
3.4.5 注意事项与常见陷阱
- 避免在 JSX 中使用复杂的逻辑
JSX 应该专注于“描述界面”,而不是承载大量判断。如果条件嵌套超过一层,请用变量或函数重构。
- 注意
false、null、undefined和0的渲染行为
React 不会渲染 true、false、null、undefined,但会渲染 0 和 NaN。使用 && 运算符时,确保左侧始终是布尔值或使用显式比较。
- 不要用
&&替换三元运算符的 else 分支
如果需要“不为 A 则显示 B”,请使用三元运算符,而不是两个 && 搭配取反,这样更清晰。
- 条件返回时注意 Hooks 规则
绝不能因为条件判断而跳过 Hooks 的调用。Hooks 必须在组件顶层、无条件地按顺序调用。例如,不能在 if 语句内部调用 useState 或 useEffect。
- 考虑使用枚举或映射对象
当条件分支基于字符串常量时,可以使用对象映射代替 switch:
const componentMap = {
loading: <Spinner />,
error: <ErrorMessage />,
empty: <EmptyState />,
success: <DataView />,
};
return <div className="card">{componentMap[status]}</div>;
条件渲染虽然基础,但用好它能让组件灵活适应多种状态,同时保持代码的可读性和可维护性。选择最适合当前场景的方式,始终以“代码清晰”为第一原则。