React 是由 Meta(原 Facebook)开发和维护的、用于构建用户界面的 JavaScript 库。2013 年开源以来,React 通过引入组件化、虚拟 DOM、JSX 和单向数据流等概念,彻底改变了前端开发的范式。无论是小型组件还是大型企业级应用(如 Facebook、Instagram、Netflix、Airbnb),React 都是当今 Web 开发的核心基础设施之一。本文从设计理念到现代特性,完整拆解 React 的核心能力。
一、React 的定位与设计哲学
1.1 React 是什么,不是什么
React 明确表示自己是一个库(Library),而不是框架(Framework):
| React 是 | React 不是 |
|---|---|
| 构建 UI 组件的工具集 | 完整的路由解决方案 → Next.js / React Router |
| 管理组件状态和生命周期 | 数据流框架 → Redux / Zustand |
| 声明式地描述 UI 长什么样 | HTTP 客户端 → Axios / Fetch |
| 高效的 DOM 更新机制 | CSS-in-JS → styled-components / Tailwind |
React 的核心哲学:UI 是状态的函数 —— 给定应用状态,React 能自动计算出 UI 应该长什么样,而开发者的职责只是描述这个映射关系。
1.2 声明式 vs 命令式
// 命令式(jQuery):告诉浏览器"怎么做"
$('#root').append($('<div>').text('Hello').addClass('red'));
// 声明式(React):告诉 React"长什么样"
function App() {
return <div className="red">Hello</div>;
}
声明式的优势:
- 可预测性:相同的输入(props + state)总是产生相同的输出(UI)
- 可组合性:组件可以像积木一样嵌套和复用
- 易于调试:状态变化链路清晰
二、核心概念
2.1 JSX:JavaScript 的语法扩展
JSX 允许在 JavaScript 中写类似 HTML 的标记语言:
// JSX 会被编译为 React.createElement() 调用
const element = <h1 className="title">Hello, world!</h1>;
// 等价于:
const element = React.createElement(
'h1',
{ className: 'title' },
'Hello, world!'
);
JSX 的关键规则:
- 只能返回一个根元素:用
<></>(Fragment)或一个<div>包裹 - 使用
className代替class(因为class是 JS 保留字) - 使用
{}嵌入 JavaScript 表达式(语句不行) - 自定义组件必须大写:
<MyComponent />vs<div /> - 所有标签必须闭合:
<img />或<input />(自闭合)
2.2 组件:UI 的构建单元
React 应用由组件树构成:
// 函数组件(现代推荐方式)
function Welcome({ name, age }) {
return <h1>Hello, {name} ({age})</h1>;
}
// 使用
<Welcome name="Alice" age={25} />
组件的三大输入:
| 输入 | 来源 | 是否能修改 | 用途 |
|---|---|---|---|
| Props | 父组件传入 | 组件自身不可修改 | 配置 / 数据来源 |
| State | 组件自身管理 | 通过 setter 修改 | 交互 / 动态数据 |
| Context | 祖先组件提供 | 通过 Provider 修改 | 跨层级共享数据 |
2.3 虚拟 DOM(Virtual DOM)
React 不直接操作真实 DOM,而是维护一棵虚拟 DOM 树:
状态变化
↓
React 计算新的虚拟 DOM 树
↓
Diff 算法比较新旧两棵树的差异
↓
只更新变化的最小 DOM 子集(Reconciliation)
↓
真实 DOM 被高效更新
这个过程的核心优化:
- Diff 复杂度从 O(n³) 降到 O(n)(启发式算法:同层比较 + key 标识)
- 批量更新:多个状态变化合并为一次 DOM 操作
- Fiber 架构(React 16+):可中断的渲染,优先处理高优先级更新
2.4 Hooks:函数组件的状态与副作用
Hooks(React 16.8 引入)让函数组件拥有了状态管理能力,彻底改变了 React 的开发模式。
最常用 Hooks:
import { useState, useEffect, useContext, useRef, useCallback, useMemo } from 'react';
function Counter() {
// useState:管理状态
const [count, setCount] = useState(0);
// useEffect:处理副作用(数据获取、订阅、手动 DOM 操作)
useEffect(() => {
document.title = `Count: ${count}`;
return () => { document.title = 'React App'; }; // 清理函数
}, [count]); // 依赖数组
// useRef:引用 DOM 或持久化值(不触发重新渲染)
const inputRef = useRef(null);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
<input ref={inputRef} />
</div>
);
}
| Hook | 用途 | 记忆点 |
|---|---|---|
useState | 管理可变状态 | const [x, setX] = useState(0) |
useEffect | 副作用处理(挂载/更新/卸载) | 依赖数组控制触发时机 |
useContext | 消费 Context(跨层级数据) | 避免 props drilling |
useRef | 引用 DOM / 存值不触发渲染 | .current 属性 |
useCallback | 缓存函数引用 | 配合 memo 的子组件优化 |
useMemo | 缓存计算结果 | 避免重复计算 |
useReducer | 复杂状态逻辑(类似 Redux) | dispatch + reducer |
useLayoutEffect | 同步执行副作用(DOM 测量) | 在浏览器绘制前执行 |
Hooks 规则(React 内部依赖调用顺序):
- 只在最顶层调用(不在 if/for 内)
- 只在 React 函数组件或自定义 Hooks 中调用
2.5 受控 vs 非受控组件
// 受控组件:React 管理表单值
function ControlledInput() {
const [value, setValue] = useState('');
return <input value={value} onChange={e => setValue(e.target.value)} />;
}
// 非受控组件:DOM 自己管理值
function UncontrolledInput() {
const inputRef = useRef(null);
const handleSubmit = () => {
console.log(inputRef.current.value); // 直接读取 DOM
};
return <input ref={inputRef} onBlur={handleSubmit} />;
}
建议:优先使用受控组件,数据流清晰、易于验证和同步。非受控组件只在性能关键场景(如大量输入框)或集成第三方库时使用。
三、现代 React(18+)核心特性
3.1 并发渲染(Concurrent Rendering)
React 18 引入并发模式,允许 React 中断低优先级更新以处理高优先级更新:
import { startTransition } from 'react';
function SearchResults() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const handleChange = (e) => {
const value = e.target.value;
setQuery(value); // 高优先级:立即更新输入框
startTransition(() => {
setResults(search(value)); // 低优先级:可以中断的搜索
});
};
return <input value={query} onChange={handleChange} />;
}
3.2 Suspense 与懒加载
import { Suspense, lazy } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
Suspense 不仅用于代码分割,React 18 还支持数据获取的 Suspense(与 <ErrorBoundary> 搭配使用)。
3.3 Server Components(RSC)
React Server Components(在 Next.js App Router 等框架中实现)让组件在服务端渲染:
// 这是 Server Component(异步,不发送到客户端)
async function PostList() {
const posts = await db.post.findMany(); // 直接访问数据库
return (
<ul>
{posts.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
);
}
- 服务端组件不会打包到客户端 JS
- 可以直接访问服务端资源(数据库、文件系统)
- 在 Next.js 中自动区分 Server/Client 组件边界
详见 React Server Components 深度解析。
四、React 生态系统
React 本身只做视图层,完整的应用需要配套生态:
| 领域 | 主流方案 | 2025 年推荐 |
|---|---|---|
| 路由 | React Router / TanStack Router | Next.js App Router |
| 状态管理 | Redux / Zustand / Jotai / Recoil | Zustand(简单)/ Jotai(原子化) |
| 样式 | styled-components / CSS Modules / Tailwind | Tailwind CSS |
| 表单 | Formik / React Hook Form | React Hook Form + Zod |
| 数据获取 | SWR / React Query (TanStack Query) | TanStack Query |
| 测试 | Jest + React Testing Library | Vitest + RTL |
| 构建工具 | Create React App / Vite | Vite / Next.js |
| 类型系统 | TypeScript | ⭐ 强烈推荐使用 |
五、什么时候选择 React?
适合 React 的场景
- 需要丰富的交互和用户界面(表单、动画、拖拽、可视化)
- 中大型应用,需要组件化管理和代码复用
- 团队熟悉 JavaScript/TypeScript 生态
- 需要React Native 同时构建移动应用
- 需要使用丰富的第三方库和工具链
不适合 React 的场景
- 纯静态站(文字为主、无交互)→ Astro / Hugo / 纯 HTML 更快
- SEO 要求极高的内容站 → Next.js(基于 React 但后端渲染)或 Astro
- 极简前端,不需要状态管理 → Alpine.js / HTMX / 原生 JS
- 纯数据大屏,需要极致性能 → Canvas / WebGL(Three.js、D3)
六、React 的演进路线
| 版本 | 核心变化 |
|---|---|
| React 15 | 基础成熟:组件化、虚拟 DOM |
| React 16 | Fiber 架构重写:可中断渲染、Error Boundaries、Portals |
| React 16.8 | Hooks 引入:函数组件革命 |
| React 17 | 无新 API,平滑升级过渡 |
| React 18 | 并发渲染、Suspense 数据获取、自动批处理 |
| React 19 | Actions、use() Hook、Server Components 稳定 |
常见问题(FAQ)
React 和 Vue 有什么区别?
详见 React vs Vue vs Svelte vs Solid 对比。一句话对比:React 更灵活(JavaScript 本身就是模板),Vue 更上手友好(模板语法更接近 HTML),Svelte 编译时优化(无虚拟 DOM),Solid 性能极致(细粒度响应式)。
什么时候开始用 useEffect?
当需要同步 React 外部系统时:DOM 操作、订阅、数据获取、定时器。如果能用纯 props/state 解决的逻辑,不要用 useEffect。
React 的 key 属性有什么用?
{items.map(item => <ListItem key={item.id} data={item} />)}
key 帮助 React 识别哪些元素改变/添加/删除,从而最小化 DOM 操作。没有 key 时 React 用索引默认,但在列表重排序时会导致性能问题和状态错乱。
React 性能优化有哪些手段?
详见 React 性能优化深度指南。核心手段:React.memo、useMemo/useCallback、代码分割(lazy/Suspense)、虚拟列表、避免 context 滥用。
React 会被淘汰吗?
短期内不会。React 拥有最大的开发者社区和最丰富的生态,Meta 每年数亿美元投入维护。Vue/Svelte 是强劲对手,但 React 仍然是企业级项目的首选。
相关阅读
- React vs Vue vs Svelte vs Solid 深度对比
- React Hooks 完全指南
- React Server Components 深度解析
- React 性能优化深度指南
- React 状态管理指南
- Next.js 完全指南专题
- React 专题导航
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。