4、React条件渲染:if/else、三元运算符、逻辑与运算符、条件渲染最佳实践

条件渲染,说白了就是「根据不同的状态,显示不同的UI」。

我刚开始写React时,觉得这玩意儿太简单了——不就是个if判断吗?结果项目一复杂,各种条件嵌套、代码冗余、可读性暴跌……嗯,这里面的门道其实不少。

今天咱们就把React条件渲染的几种方式掰开揉碎,看看什么时候用if/else,什么时候用三元,什么时候用&&,以及我踩过的那些坑。

4.1 最基本的if/else

在JSX里,你不能直接写if语句。因为JSX本质上是个语法糖,最终会被编译成React.createElement调用。但我们可以把if/else放在JSX外面。

function UserGreeting({ user }) {
  if (user) {
    return <h1>欢迎回来,{user.name}!</h1>;
  } else {
    return <h1>请先登录</h1>;
  }
}

这种方式最直观,逻辑清晰。我在项目中处理复杂的多分支条件时,首选就是if/else。

我的习惯:如果条件分支超过3个,或者每个分支的JSX结构比较复杂,我会用if/else提前return。这样JSX部分就干净了。

4.2 三元运算符:简洁但别滥用

三元运算符是JSX里最常用的条件渲染方式。它本质上就是个表达式,可以直接写在JSX的花括号里。

function StatusBadge({ isActive }) {
  return (
    <span className={isActive ? 'badge-success' : 'badge-danger'}>
      {isActive ? '已激活' : '未激活'}
    </span>
  );
}

三元运算符适合「二选一」的场景。但如果你嵌套使用,代码就会变得很难读。

我曾经踩过的坑:有一次写了个三层嵌套的三元表达式,自己过了一周回来看,愣是看了五分钟才搞明白逻辑。从那以后我给自己定了个规矩:三元嵌套不超过一层。
// ❌ 不推荐:三层嵌套,可读性极差
return (
  <div>
    {isAdmin ? (isSuper ? '超级管理员' : '普通管理员') : (isVip ? 'VIP用户' : '普通用户')}
  </div>
);

// ✅ 推荐:提取成函数或变量
const getRoleLabel = () => {
  if (isAdmin) return isSuper ? '超级管理员' : '普通管理员';
  return isVip ? 'VIP用户' : '普通用户';
};
return <div>{getRoleLabel()}</div>;

4.3 逻辑与运算符:简洁的「有则显示」

逻辑与(&&)是React条件渲染里最优雅的方式之一。它特别适合「满足条件就显示,不满足就什么都不显示」的场景。

function NotificationBadge({ count }) {
  return (
    <div>
      消息
      {count > 0 && <span className="badge">{count}</span>}
    </div>
  );
}

这里有个细节要注意:count > 0 && ... 当count为0时,表达式结果是0,React会渲染出「0」。嗯,这是个经典坑。

避坑指南:使用&&时,确保左侧表达式的结果一定是布尔值。如果左侧可能是数字0、空字符串等「假值」,记得先转成布尔。
// ❌ 坑:当list.length为0时,会渲染出0
{list.length && <List data={list} />}

// ✅ 正确写法
{list.length > 0 && <List data={list} />}
// 或者
{!!list.length && <List data={list} />}

4.4 条件渲染的几种特殊场景

4.4.1 使用变量存储JSX

当条件逻辑比较复杂时,我习惯先把JSX存到变量里,再统一渲染。

function Dashboard({ role }) {
  let dashboardContent;

  if (role === 'admin') {
    dashboardContent = <AdminPanel />;
  } else if (role === 'editor') {
    dashboardContent = <EditorPanel />;
  } else {
    dashboardContent = <UserPanel />;
  }

  return (
    <div className="dashboard">
      <Header />
      {dashboardContent}
      <Footer />
    </div>
  );
}

这种方式的好处是:JSX结构一目了然,条件逻辑被隔离在变量赋值阶段。

4.4.2 立即执行函数(IIFE)

有时候你不想把逻辑抽到外面,又需要在JSX里写复杂条件。这时候可以用IIFE。

function ComplexComponent({ status }) {
  return (
    <div>
      {(() => {
        switch (status) {
          case 'loading':
            return <Spinner />;
          case 'error':
            return <ErrorMsg />;
          case 'empty':
            return <EmptyState />;
          default:
            return <DataList />;
        }
      })()}
    </div>
  );
}

说实话,IIFE在团队里争议挺大的。我个人建议:除非是临时性的小逻辑,否则还是抽成单独的函数或组件更合适。

4.5 条件渲染的最佳实践

写了几年React,我总结了几条条件渲染的原则,分享给你:

场景 推荐方式 原因
二选一,且JSX简单 三元运算符 简洁直观,一行搞定
多分支(3个以上) if/else 或 switch 逻辑清晰,易于维护
有则显示,无则隐藏 逻辑与 && 最优雅的写法
条件复杂,JSX结构大 提取为子组件 职责单一,可复用
条件决定整个组件内容 提前return 减少嵌套,提前退出
我的核心原则:条件渲染的代码,应该像一篇好文章——别人读一遍就能理解。如果你自己写完都觉得绕,那一定不是好代码。

4.6 一个完整的实战例子

最后,咱们看一个综合的例子。假设我们要做一个用户列表页面,有加载中、空数据、错误、正常显示四种状态。

function UserListPage() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetchUsers()
      .then(data => setUsers(data))
      .catch(err => setError(err.message))
      .finally(() => setLoading(false));
  }, []);

  // 加载中
  if (loading) {
    return <LoadingSkeleton />;
  }

  // 错误状态
  if (error) {
    return <ErrorState message={error} onRetry={fetchUsers} />;
  }

  // 空数据
  if (users.length === 0) {
    return <EmptyState />;
  }

  // 正常渲染
  return (
    <div>
      <h2>用户列表(共{users.length}人)</h2>
      <UserList users={users} />
    </div>
  );
}

你看,这里用了提前return的方式,每个状态都独立处理。代码从上往下读,逻辑非常清晰。这就是我推荐的做法。

好了,条件渲染就聊到这儿。说白了就是:选对工具,保持简洁,让别人能看懂。下一章咱们聊聊列表渲染和key的重要性,那个坑更多……