1

问题背景

作为一名 React 开发者,在 JSX 中编写条件渲染时总会遇到一些烦恼。看看这些常见的代码:

{isVisible && (
  <>
    <Header />
    <Content />
  </>
)}

{
  isLoggedIn 
  ? <UserDashboard /> 
  : <LoginForm />
}

这种写法虽然能用,但存在以下问题:

  • 大量的花括号和括号使代码难以阅读
  • 嵌套条件时结构更加混乱
  • 代码不够优雅直观

从开发的角度来看,这似乎不是一个主要的痛点,但它更像是一种沉闷而持久的烦恼😖。它常常让我感到沮丧,尤其是当代码结构变得复杂时--三元运算让我的代码看起来很难看,也更难理解🤯。

灵感来源:Solid.js 的优雅方案

从 Solid.js 框架获得灵感,可以创建一个 Show 组件来优化条件渲染的写法:

// Show 组件类型定义
interface ShowProps<T> {
  when: T | undefined | null | false;
  fallback?: React.ReactNode;
  children: React.ReactNode | ((item: T) => React.ReactNode);
}

实现方案

创建一个简单但强大的 Show 组件:

function Show({ when, fallback = null, children }) {
  return when ? children : fallback;
}

使用示例

1. 基础条件渲染

// ❌ 旧写法
{isLoading && <Spinner />}

// ✅ 新写法
<Show when={isLoading}>
  <Spinner />
</Show>

2. 条件分支渲染

// ❌ 旧写法
{isAdmin 
  ? <AdminPanel /> 
  : <UserPanel />
}

// ✅ 新写法
<Show 
  when={isAdmin}
  fallback={<UserPanel />}
>
  <AdminPanel />
</Show>

3. 复杂条件渲染

// ❌ 旧写法
{isCommentsEnabled && (
  <>
    <CommentsHeader />
    {comments.map(comment => (
      <CommentItem key={comment.id} {...comment} />
    ))}
    {isLoggedIn && <CommentForm />}
  </>
)}

// ✅ 新写法
<Show when={isCommentsEnabled}>
  <CommentsHeader />
  {comments.map(comment => (
    <CommentItem key={comment.id} {...comment} />
  ))}
  <Show when={isLoggedIn}>
    <CommentForm />
  </Show>
</Show>

4. 带数据处理的条件渲染

// ❌ 旧写法
{user && (
  <div>
    Welcome, {user.name}!
    {user.isAdmin && <AdminBadge />}
  </div>
)}

// ✅ 新写法
<Show when={user}>
  {(userData) => (
    <div>
      Welcome, {userData.name}!
      <Show when={userData.isAdmin}>
        <AdminBadge />
      </Show>
    </div>
  )}
</Show>

扩展功能

还可以添加一些实用的功能:

// 支持异步数据
const AsyncShow = ({ when, fallback, children }) => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    Promise.resolve(when).then(result => {
      setData(result);
      setIsLoading(false);
    });
  }, [when]);

  if (isLoading) return fallback;
  return data ? children : null;
};

// 使用示例
<AsyncShow 
  when={fetchUserData()} 
  fallback={<Loading />}
>
  {user => <UserProfile data={user} />}
</AsyncShow>

这个简单的组件不仅能让代码更加清晰易读,还能提升开发效率。有时候最简单的改进反而能带来最大的收益!🎉

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

王大冶
68k 声望104.9k 粉丝