React 与组件思维
React 与组件思维 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
这一课帮你建立 React 最核心的心智模型:界面由组件拼成,组件是「输入 → 界面描述 → 交互」的闭环。读完你能把一块完整的页面按职责拆成组件,并说清每个组件各自管什么、互相怎么衔接。
问题场景
假设学习工作台的首页是这样写出来的:一个 Home 函数返回了三百多行 JSX——顶部导航、课程卡片、学习统计、页脚全在里面。现在产品要求「课程卡片上加一个收藏按钮」,你从三百行里翻出卡片那 40 行,改完又发现统计区也想用同样的卡片,只能复制粘贴一份。改一处、抄一处,错误就是这么来的。
核心解释
React 组件本质上是一个函数:接收输入,返回一段界面描述(JSX)。拆组件的依据不是「代码行数」,而是职责——一个组件只应该因为一个原因被修改。课程卡片因为需求变化而改,页脚不会跟着改,它们就不该待在同一个函数里。
每个组件内部都有一个闭环:
- 输入:从外部拿到的数据(props)和自己私有的状态(state);
- 展示:根据输入返回 JSX,描述「这个状态下界面长什么样」;
- 交互:用事件处理(如
onClick)响应用户操作,更新自己的状态——状态一变,React 重新调用这个函数,界面随之更新。
用代码表达这个闭环,就三样东西:
function FavButton() {
const [faved, setFaved] = useState(false); // 输入之外自己的状态
return (
<button onClick={() => setFaved(!faved)}> {/* 交互:改状态 */}
{faved ? "已收藏" : "收藏"} {/* 展示:由状态推导 */}
</button>
);
}
拆分时先找「重复出现的结构」(三张课程卡片就是同一个组件用三次),再找「独立的改动原因」(导航、内容、页脚分开)。组件名必须大写开头,React 靠这个区分自定义组件和 <div> 这类原生标签。
function CourseCard({ course }) {
return (
<div className="card">
<h3>{course.title}</h3>
<p>{course.summary}</p>
</div>
);
}
function Home() {
return (
<main>
<CourseCard course={courses[0]} />
<CourseCard course={courses[1]} />
</main>
);
}
示例拆解
实验区把一个迷你工作台拆成了三个组件,关键点如下:
Header只管标题区,无输入、无状态——最简单的一类组件;CourseCard接收一个course对象作为输入,内部用useState记录「是否已收藏」,点击按钮翻转状态,界面上的标记跟着变;App负责把组件按页面结构组合起来,同一份CourseCard传三份不同数据,就是三张不同的卡片。
验证方式:在实验区点任意卡片的「收藏」按钮,只有那张卡变化——因为收藏状态在各组件内部独立,互不干扰。这正是拆组件换来的隔离性。
动手任务
打开本课实验区,完成三个小改动:
- 给
CourseCard增加一个显示课时数的区域,数据来自course.lessons(先在数据里补上这个字段)。 - 再往页面里加一张第四门课的卡片,体会「复用」和「复制粘贴」的差别。
- 把卡片上的收藏文字改成「收藏 / 已收藏」两种状态文案,观察你只需要改
CourseCard一个组件。
常见错误
- 组件名小写开头:写成
function courseCard(),JSX 里的<courseCard />会被 React 当成未知的 HTML 标签,页面空白且不报明显错误。 - 把整页塞进一个组件:所有状态都堆在一起,任何小改动都可能牵动整页;先按「独立改动原因」切分。
- 拆得过细:一个
<p>都包成组件,组合成本超过收益;小组件要在「真的会被复用或独立变化」时才拆。 - 在组件函数内部再定义组件:每次渲染都会创建新的组件类型,内部状态会被整个丢掉;组件要么定义在顶层,要么通过 props 传递。
检查与复盘
完成下方检查题确认理解。自查清单:
- 拿到一块界面,能先说出「哪几块会因为不同原因被改动」,再动手拆
- 能对任意一个组件说出它的输入是什么、状态是什么、交互改了哪个状态
- 知道组件名为什么必须大写,以及嵌套定义组件会出什么问题
参考资料
- React 官方文档:你的第一个组件 —— 组件的定义与 JSX 返回值的官方入门讲解
- React 官方文档:用 React 描述界面 —— 声明式界面与组件组织的整体视角
读完这一课了?
标记完成后,工作台会安排接下来的学习。