R03第 1 / 1 课时未开始内容版本 1.0.0 · 核验于 2026-10-26

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 感知的状态),再回想这为什么危险。

验证方式:改父数据后界面立即更新;说明「更新来自数据拥有方的变化,而不是子组件的私改」。

动手任务

打开本课实验区,完成三个小改动:

  1. 给 CourseCard 增加可选 prop highlight(默认 false),为 true 时卡片加浅黄背景。
  2. 给第二张卡片补上标签数据,确认不写默认值逻辑时「不传」和「传空数组」的区别。
  3. 把「子组件里改 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 内部私有可变
  • 写组件时先列输入清单,区分必需与可选,可选的都有默认值
  • 需要改数据时,知道去数据拥有的一方改,让数据流保持单向

参考资料

动手实验
动手实验
预览
点击「运行」在隔离沙箱中预览
检查题共 2 题,提交后立即显示解析
答案由服务端判定;答错的题会自动进入复习计划。
Q1单选简单

子组件收到 props.count 为 3,希望界面上的数字变成 4。正确的做法是?

Q2读代码中等

阅读代码(React 18+)。分别用 <Greet name='阿明' /> 和 <Greet /> 渲染,两个按钮上各显示什么?

function Greet({ name = '同学', suffix = '!' }) {
  return <button>{`你好,${name}${suffix}`}</button>;
}

export default function App() {
  return (
    <>
      <Greet name='阿明' />
      <Greet />
    </>
  );
}

读完这一课了?

标记完成后,工作台会安排接下来的学习。

Command Palette

Search for a command to run...