React中如何优雅地处理条件渲染
React 中如何优雅地处理条件渲染一句话总结三元表达式适合「二选一」 适合「显示/隐藏」立即执行函数 IIFE 复杂逻辑兜底抽出子组件才是终极方案。别在 JSX 里写 if-else用对了方式条件渲染既干净又不容易出 bug正文目录条件渲染有哪些方式5 大高频场景 代码示例万能兜底条件渲染决策表预防 checklist不再踩坑一句话总结一、条件渲染有哪些方式问题背景JSX 本质是 JavaScript不能直接写if-elseReact 提供了多种条件渲染方式但用错了会导致渲染异常、性能浪费或代码可读性差。方式适用场景特点三元表达式? :二选一简洁返回值逻辑与显示/隐藏短路求值IIFE 立即执行函数复杂逻辑可写 if-else但可读性差抽取子组件复用/复杂条件最推荐可维护switch IIFE多条件分支比 if-else 清晰enum对象映射状态映射渲染最优雅的多分支// ❌ 错误JSX 中不能直接写 if-else function App({ status }) { return ( div if (status loading) { // 这会被当字符串渲染 Loading / } /div ) }二、5 大高频场景 代码示例场景 1加载状态 → 用 最常见场景数据没加载完显示 Loading加载完显示内容。// ✅ 正确 适合「满足条件才显示」 function UserList({ users, loading }) { return ( div {loading Spinner /} {!loading users.map(u div key{u.id}{u.name}/div)} /div ) }// ❌ 错误 与数字 0 的坑 function App({ count }) { return ( div {count Badge text{count} /} /div ) } // count 为 0 时渲染出 0 而不是什么都不显示// ✅ 正确避免 0 的坑 function App({ count }) { return ( div {count 0 Badge text{count} /} {/* 或 */} {!!count Badge text{count} /} /div ) }场景 2二选一 → 用三元表达式登录/未登录、有数据/空状态用三元最清晰。// ✅ 正确三元表达式二选一 function Greeting({ user }) { return ( div {user ? Welcome name{user.name} / : LoginButton /} /div ) }// ❌ 不推荐 叠 实现二选一 function Greeting({ user }) { return ( div {user Welcome name{user.name} /} {!user LoginButton /} /div ) } // 能用但啰嗦且两个条件都执行场景 3多状态切换 → 用对象映射loading / success / error 三种状态用对象映射比 if-else 优雅得多。// ✅ 正确对象映射清晰优雅 function StatusView({ status, data, error }) { const statusMap { loading: Spinner /, success: DataList data{data} /, error: ErrorMessage error{error} /, empty: EmptyState / } return div{statusMap[status] ?? DefaultView /}/div }// ❌ 糟糕嵌套三元表达式难以阅读 function StatusView({ status, data, error }) { return ( div {status loading ? Spinner / : status success ? DataList data{data} / : status error ? ErrorMessage error{error} / : EmptyState /} /div ) }场景 4复杂条件逻辑 → 抽子组件条件里有循环、有副作用、有复杂判断抽成子组件最清晰。// ✅ 正确复杂逻辑抽子组件 function ProductList({ products, filter, sort }) { return ( div ProductGrid products{products} filter{filter} sort{sort} / /div ) } function ProductGrid({ products, filter, sort }) { const visible products .filter(filter) .sort(sort) if (visible.length 0) { return EmptyState message没有符合条件的商品 / } return ( ul {visible.map(p ( li key{p.id}{p.name} - ¥{p.price}/li ))} /ul ) }// ❌ 糟糕在 JSX 里塞一堆逻辑 function ProductList({ products, filter, sort }) { return ( div {(() { const visible products.filter(filter).sort(sort) if (visible.length 0) { return EmptyState message没有符合条件的商品 / } return ( ul {visible.map(p ( li key{p.id}{p.name} - ¥{p.price}/li ))} /ul ) })()} /div ) } // IIFE 能用但可读性差lint 也不推荐场景 5条件 className → 用工具函数条件渲染不只是组件className 的条件拼接也是高频场景。// ✅ 正确用 clsx / classnames 工具 import clsx from clsx function Button({ variant, size, disabled, children }) { return ( button className{clsx( btn, btn-${variant}, // btn-primary / btn-secondary btn-${size}, // btn-sm / btn-lg { btn-disabled: disabled, // 条件为 true 时添加 btn-active: !disabled } )} {children} /button ) }// ❌ 糟糕手动拼接字符串 function Button({ variant, size, disabled }) { let className btn btn- variant btn- size if (disabled) { className btn-disabled } else { className btn-active } return button className{className}Click/button }三、万能兜底条件渲染决策表场景推荐方式示例满足条件才显示{loading Spinner /}二选一三元表达式{user ? A / : B /}三选一及以上对象映射statusMap[status]复杂逻辑判断抽子组件ProductGrid ... /条件 classNameclsx工具clsx(btn, { active })数字 0 的坑 0 或!!{count 0 Badge /}组件 show/hide 频繁切换CSSdisplaydiv style{{ display: show ? : none }}万能决策流程条件有几个分支 → 1 个满足才显示→ 用 → 2 个 → 用三元表达式 → 3 个及以上 → 用对象映射 → 逻辑太复杂 → 抽子组件// 万能模板 function View({ status, data, error }) { // 复杂逻辑先抽出来 if (status loading) return Spinner / if (status error) return ErrorMessage error{error} / if (!data || data.length 0) return EmptyState / // 简单条件用 return ( div {data.length 10 Pagination total{data.length} /} DataList data{data} / /div ) }四、预防 checklist不再踩坑左侧是数字时用 0或!!避免0被渲染不要在 JSX 中写if-else用三元或 IIFE嵌套三元超过 2 层 → 换对象映射或抽子组件IIFE 只在万不得已时用优先抽子组件组件内提前return处理 loading/error 状态减少嵌套条件 className 用clsx/classnames不要手动拼字符串频繁切换的组件用 CSSdisplay而非卸载/挂载保留状态switch语句放在组件外部或 IIFE 中不要直接写在 JSX五、一句话总结一个分支用 两个分支用三元三个以上用对象映射逻辑复杂就抽子组件——条件渲染的本质就是把 if-else 翻译成 JSX 能接受的形式。最后问候亲爱的朋友们并邀请你们阅读我的全新著作 《React进阶之路》