问题背景
作为一名 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>
这个简单的组件不仅能让代码更加清晰易读,还能提升开发效率。有时候最简单的改进反而能带来最大的收益!