Props 与数据传递
Props 与数据传递 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
这一课解决「组件之间怎么传数据」:props 是什么、必需和可选输入怎么设计、为什么 props 只读。读完你能用 props 构建一张可配置的课程卡片,并解释数据在组件树里的流向。
问题场景
R01 里的课程卡片显示了固定文案,现在要让同一个 CourseCard 显示不同课程:标题、难度、可选标签、是否展示难度徽标都由外部决定。第一版把数据写死在组件里,第二版想偷懒直接改传入的对象:
function CourseCard(props) {
props.course.level = "intro"; // 想把难度统一改成入门
return <h3>{props.course.title}</h3>;
}
界面没报错,但父组件的数据被偷偷改掉了,其他用到这份数据的地方全部遭殃——这类 bug 找起来极费劲。
核心解释
props 是组件从父组件拿到的只读输入。 父组件写 <CourseCard course={x} showLevel={false} />,子组件从 props 上读值。记住两条铁律:
一、props 只读。 React 的数据流是单向的:父 → 子。修改 props 不会触发重新渲染,还会破坏「数据只有一个拥有者」的约定。想改数据,去数据拥有的一方(父组件)改,再通过 props 流下来。组件内自己会变的数据用 state,那是 R08 之后的话题。
二、用解构和默认值声明输入。 直接写 function CourseCard(props) 看不出组件需要什么;解构参数让输入一目了然,并顺手给可选 prop 设默认值:
function CourseCard({ course, showLevel = true, tags = [] }) {
return (
<div className="card">
<h3>{course.title}</h3>
{showLevel && <span>{course.level}</span>}
{tags.map((tag) => (
<span key={tag}>#{tag}</span>
))}
</div>
);
}
这里 course 是必需输入——没有它组件直接崩溃;showLevel、tags 是可选输入,调用方不传就落到默认值。设计 props 时先问「哪些是缺了就没法工作的」,其余都做成可选。
示例拆解
实验区用三张卡片演示同一组件的不同配置,关键点如下:
- 三张卡片都渲染
CourseCard,区别只在 props:第一张全量传、第二张不传tags(默认空数组,不渲染标签区)、第三张传showLevel={false}隐藏难度徽标; - 顶部有一个「在父组件改标题」按钮:点击后父组件改的是自己手里的数据,新数据经 props 流下来,三张卡片同步更新——正确 direction;
- 另有一个「子组件里改 props」按钮:调用的函数试图给 props 对象赋值,观察界面纹丝不动(改的不是 React 感知的状态),再回想这为什么危险。
验证方式:改父数据后界面立即更新;说明「更新来自数据拥有方的变化,而不是子组件的私改」。
动手任务
打开本课实验区,完成三个小改动:
- 给
CourseCard增加可选 prophighlight(默认false),为true时卡片加浅黄背景。 - 给第二张卡片补上标签数据,确认不写默认值逻辑时「不传」和「传空数组」的区别。
- 把「子组件里改 props」按钮的函数改成先复制再返回新对象(不真的改 props),理解「新建数据」和「改旧数据」的边界。
常见错误
- 直接修改 props 或其嵌套对象:界面不更新且污染父组件数据;要改就复制后放 state 或交回父组件。
- 必需 prop 忘传:
course.title直接抛「Cannot read properties of undefined」;关键输入缺失时宁可早崩,也可用默认值兜底。 - 把默认值写成共享对象:
tags = []每次调用都是新数组,没问题;但如果默认值来自外部常量且被原地 push,所有未传该 prop 的组件会互相污染。 - 用 props 传组件:写
<CourseCard course="cards" />传的是字符串;花括号course={courses[0]}才是传值,没花括号传的永远是字符串。
检查与复盘
完成下方检查题确认理解。自查清单:
- 能说出 props 与 state 的分工:外部传入且只读 vs 内部私有可变
- 写组件时先列输入清单,区分必需与可选,可选的都有默认值
- 需要改数据时,知道去数据拥有的一方改,让数据流保持单向
参考资料
- React 官方文档:向组件传递 Props —— props 的定义、默认值与只读约定
- React 官方文档:保持组件纯粹 —— 为什么不该修改输入
读完这一课了?
标记完成后,工作台会安排接下来的学习。