大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
条件渲染与列表
这一课你将能做到
- 用三元、
&&、提前 return 切换界面 - 用
map渲染列表并写好key - 避开
0 && <Component />把 0 显示出来的坑
为什么要学
未登录显示「登录」;已登录显示名字。
课时列表有数据就展示行,没数据就显示「暂无站点」。
这些都是条件渲染和列表渲染。人话:根据数据决定「画什么、画几份」。
本站 /learn、课程目录、刷题列表全是「空态 + map」组合。不会这个,页面要么假空白,要么一套 HTML 复制十二遍。
先建立图像
{user ? <Profile user={user} /> : <LoginLink />}
{items.length === 0 && <p>暂无站点</p>}
{items.map((x) => <Card key={x.id} title={x.title} />)}
三件事:二选一、有则显示、重复生成。
跟着做
步骤 1:提前 return(最好读)
function Header({ user }) {
if (!user) {
return <a href="/login">登录</a>;
}
return <span>你好,{user.name}</span>;
}
先处理「没有」的情况,后面的 JSX 假设数据已经齐了。加载中也可以:if (loading) return <p>加载中…</p>。
步骤 2:三元(真正的二选一)
<button type="button">{saving ? "保存中…" : "离开本站"}</button>
适合短文案。JSX 很长时拆成变量或提前 return,别套三层三元。
步骤 3:&& 的数字坑(必背)
const count = 0;
return (
<div>
{count && <p>有 {count} 条</p>}
{/* 会渲染出 0!因为 0 是假值,但 React 仍会把 0 当孩子显示出来 */}
</div>
);
更稳:
{count > 0 && <p>有 {count} 条</p>}
// 或
{count ? <p>有 {count} 条</p> : null}
空字符串 "" && ... 也可能画出空白异常。左侧用真正的布尔值(length === 0、count > 0)。
步骤 4:列表 + 空态(一套完整)
function LessonList({ lessons }) {
if (!lessons || lessons.length === 0) {
return <p>暂无课程</p>;
}
return (
<ul>
{lessons.map((l) => (
<li key={l.id}>
{l.title} {l.done ? "✓" : ""}
</li>
))}
</ul>
);
}
key 用业务 id;不要用 Math.random()(每次渲染都变,React 会以为全是新项)。
会插入/删除/排序时不要用下标当 key:中间插一项,后面项的下标全变,输入框焦点会「跳」到别人身上。
步骤 5:列表里再套条件
{lessons.map((l) => (
<li key={l.id} hidden={!l.visible}>
{l.title}
</li>
))}
更常见是 filter 再 map:先 lessons.filter((l) => l.visible).map(...),空了再走空态。
步骤 6:列表 key 稳定
{tracks.map(t => <li key={t.slug}>{t.title}</li>)}
// key={index} 在插入/删除时易错位——仅静态列表可勉强
讲清楚要点
- 三种条件写法:提前 return、三元、
&&(注意假值)。 - 列表必须 key:帮助 React 识别「哪一项是同一项」。写在
map返回的最外层元素上。 - 空状态也是一种 UI,不要假空白让用户以为坏了。
- 条件 + 列表常一起出现:先判 loading,再判空,再 map。
- 不要在 map 里用 index 当复合组件内部 state 的靠山——重排会绑错。
你可能会懵的地方
-
key 写在哪里?
写在map返回的最外层。写在里面的<span key>而外层是<li>不算给这一项。 -
可以 index 当 key 吗?
静态永不重排的短展示列表勉强;会排序/插入/删除、或项内有输入框/勾选时用真 id。 -
&&右侧一定渲染组件吗?
左侧为真才渲染;左侧若是0/"",可能把假值本身画出来。 -
两个列表项能否同一个 key?
不能。兄弟之间 key 要唯一。 -
&&渲染 0?
{count && <Badge />}在 count=0 时可能打出 0。用count > 0 &&或三元。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
{count && ...} count 可能为 0 | 页面冒出 0 | 用 count > 0 |
| 无 key | 警告/错乱 | 稳定 id |
| 空列表什么都不渲染 | 用户以为坏了 | 写「暂无」 |
key={index} 且可重排 | 状态绑错行 | 业务 id |
| 三元套三元套三元 | 不可读 | 提前 return / 变量 |
| key 用随机数 | 每次挂载丢失状态 | 稳定业务 id |
用 map 忘 return | 空白 | 写 return 或简写 () => <el/> |
自测三问
- 为何
0 && <X />会显示 0? - key 应该来自哪里?下标什么时候绝对别用?
- 空列表怎样给用户更好体验?loading 呢?
小结一句话
条件切换 UI 要写清真假值;列表用 map + 稳定 key,并处理空状态。
动手加深
空列表、加载中、有数据三态各写一个分支;禁止「没数据也 map 出 undefined」。
跟着做(加厚 · react-conditional)
步骤:最小可运行对照
在 Vite 或 Next 练习页粘贴本课核心示例,改一个输入,确认屏幕变化符合预期。再故意写一个错法表里的写法,看控制台/界面如何坏,然后改回。
每个概念都问:state 在谁手里?UI 哪一块会因它重绘?
操作顺序:打开对应文件 → 改一处可观察点(文案、类型、className 或分支)→ 保存看结果 → 复原或留下有意义的小改动。
步骤:错法故意练一次
先按「用 jQuery 式直接改 DOM 冒充完成」做 30 秒(或在注释里写出若这样做会怎样),再改成「改数据(state/props)让 UI 推导出来」。 目的不是留坑,而是让失败现象进长期记忆。
你可能会懵的地方(加厚)
-
热更新后状态丢了?
正常:整树重挂会重置 state。用 key 或外提状态保留;开发期别被吓到。 -
和文档示例不一致?
以你锁的 React 大版本 + react.dev 为准;旧博客的 class 组件示例仅作历史阅读。 -
这课和前后课怎么接?
回看大纲上一课的小结一句、下一课标题;用自己的话写「本课产出什么可观察结果」。写不出来就重做跟着做。
错法对照(加厚)
| 错法 | 问题 | 正解 |
|---|---|---|
| 用 jQuery 式直接改 DOM 冒充完成 | 假完成/埋雷 | 改数据(state/props)让 UI 推导出来 |
| 只看不敲 | 第二天全忘 | 至少跑通本课步骤 |
| 跳过自测三问 | 以为会了 | 闭卷答再对稿 |
延伸
- Conditional Rendering · Rendering Lists
- 下一课:useEffect——和外部世界同步。