很多人第一次接触 React,会把 JSX、props 和 state 看成三块独立知识点:JSX 是语法、props 是传值、state 是状态。可一旦进入真实页面,你会发现这三者其实是一套完整的交互表达链路:JSX 负责把结构写出来,props 负责表达输入边界,state 负责承接本地变化。
所以这一篇真正要讲的,不是语法表,而是 React 最基础的组件协作模式是怎样建立起来的。
JSX 为什么不只是“HTML 写在 JS 里”?
JSX 最容易被误解成一种语法糖。它当然是语法层工具,但它真正重要的地方在于:它把界面结构和状态表达更自然地放进了同一个组件单元里。你在 JSX 里表达的,不只是标签长什么样,而是:
- 某个属性由哪份状态驱动;
- 某段结构在什么条件下出现;
- 某个回调由谁提供;
- 某个组件在组件树里扮演什么角色。
所以 JSX 的重点从来不是像不像 HTML,而是它是否让组件结构和数据关系更容易读懂。
props 的核心作用是什么?
props 不只是“父传子”的管道,它真正表达的是:这个组件有哪些输入边界。也就是说,一个组件拿到 props 的时候,本质上是在说:
- 我依赖这些外部输入;
- 我不拥有这些输入的最终控制权;
- 如果需要让外部知道某件事,要通过回调或事件意图表达出去。
这意味着 props 设计得好坏,会直接影响组件是否清晰、是否可复用。模糊的 props 命名和不稳定的输入结构,通常是组件很难维护的重要原因。
state 为什么是组件交互的起点?
state 承接的是组件内部会变化的数据,比如:
- 输入值;
- 开关状态;
- 局部 loading;
- 当前 tab;
- 某块区域是否展开。
真正重要的不是“会不会用 useState”,而是知道哪些状态该留在本地,哪些不该。React 项目里最常见的问题之一,就是局部状态放得过高,或者本该外部控制的状态又被组件内部偷偷接管。
props 和 state 在真实组件里是什么关系?
更成熟的理解通常是:
- props 表达外部输入;
- state 承接组件内部变化;
- JSX 把这两者最终映射成可见界面。
也就是说,一个组件之所以能真正形成交互单元,往往就是因为这三者形成了闭环:外部给输入、内部处理变化、界面据此更新。
什么时候应该“提升状态”?
这是 React 基础里非常重要的判断。状态提升的本质,不是为了“更规范”,而是因为某份状态已经不只属于单个子组件了。典型场景包括:
- 多个子组件共享同一份筛选条件;
- 表单字段需要由父层统一提交;
- 弹窗状态要和列表操作协同;
- 某个派生结果要同时影响多个区域。
一旦状态已经成为多个组件的共同事实,就更适合放到它们的共同父层,而不是各自偷偷维护一份副本。
什么时候不该盲目提升状态?
因为提升状态也有代价。状态一旦被放得过高,常见后果包括:
- 局部组件失去独立性;
- 父组件越来越重;
- 不相关区域也跟着受影响;
- 组件树的职责边界开始模糊。
所以更稳的原则从来不是“状态越高越统一”,而是“状态放在最低的、但又能满足共享需求的那一层”。
把 JSX、props 和 state 放回项目里,最重要的是什么?
一个更稳的判断顺序通常是:
1. 先明确组件结构;2. 再定义组件输入边界;3. 再决定哪些变化留在本地;4. 多组件共享时,再考虑状态提升。
只要这套顺序稳定下来,基础组件和页面组件都会清晰很多。
最常见的几个误区
1. 把 JSX 当纯模板,不思考数据关系
这样很容易写出结构能跑、但边界混乱的组件。
2. props 命名模糊
会让组件职责越来越难理解。
3. 状态要么全留本地,要么全抬太高
这两种极端都会让项目失衡。
4. 看见交互就先上 Effect
很多本地交互其实只靠 state 和 props 就足够清楚。
总结
JSX、props 和 state 不是三块分离知识点,而是 React 组件最基础的交互表达闭环。JSX 负责结构表达,props 负责输入边界,state 负责本地变化。只要你能始终围绕“结构、输入、变化”这三件事来组织基础组件,后面的 Hook 和复杂协作就会稳很多。