前置知识: JavaScript、HTML5、CSS

概述与环境配置

6 min入门

React 概述、发展历史、React 19 新特性、环境搭建与 JSX 语法基础。

本节为增量补充,帮助你选择 React 与元框架版本。

  • React:19.2.x 为当前稳定版(最新 19.2.8,2026-07);Server Components、Actions 等已是 React 19 后的主推形态。
  • 元框架:Next.js 16.2.x 为 Active LTS(16.0 于 2025-10 发布,16.2.11 为 2026-07 安全版本)。新项目建议直接使用 Next.js 16 + App Router。
  • 学习建议:先掌握纯 React(组件、Hook、状态),再进入 Next.js 的服务器组件与数据获取。

1. React 概述

React 是由 Meta(原 Facebook)开发并维护的开源 JavaScript UI 库,于 2013 年 5 月首次开源。它采用声明式编程范式,以组件化思想构建用户界面,是目前全球使用最广泛的前端框架之一。

1.1 核心理念

理念说明
声明式描述 UI 应该是什么样子,而非如何一步步操作 DOM
组件化将 UI 拆分为独立、可复用的组件,每个组件管理自己的状态和渲染
一次学习,到处编写React 可用于 Web、Native(React Native)、VR 等多个平台
单向数据流数据从父组件通过 Props 向下流动,状态变更通过回调向上传递

1.2 发展历史

版本时间里程碑
React 0.32013.05首次开源
React 0.142015.10拆分 react-dom,引入无状态函数组件
React 152016.04正式版本号,Fiber 架构开始酝酿
React 162017.09Fiber 架构落地,Error Boundaries、Portals、Fragment
React 16.82019.02Hooks 正式发布,函数组件成为主流
React 172020.10事件委托机制变更,为并发特性铺路
React 182022.03并发渲染(useTransition/useDeferredValue)、自动批处理、流式 SSR、useId
React 192024.12Server Components、Actions、use() Hook、useOptimistic、ref 作为 prop
React 19.12025.03Owner Stacks(开发期调试)等
React 19.22025.10<Activity>、useEffectEvent、Partial Pre-rendering 支持等

1.3 React 19 核心新特性概览

React 19 是一次重大更新,主要围绕以下方向:

  • React Server Components (RSC):服务端组件正式稳定,减少客户端 JavaScript 体积
  • Actions:简化表单提交和异步状态管理
  • 新 Hooks:use()、useFormStatus、useOptimistic、useActionState
  • 改进的 Suspense:支持服务端流式渲染
  • ref 作为 prop:函数组件不再需要 forwardRef
  • 文档元数据支持:<title>、<meta> 等标签可直接在组件中声明
  • 样式表支持:通过 precedence 控制样式表加载顺序

2. 环境搭建

2.1 使用 Vite 创建项目(推荐)

Vite 是目前最流行的前端构建工具,启动速度极快,热更新即时。

# 使用 npm
npm create vite@latest my-react-app -- --template react-ts

# 使用 pnpm
pnpm create vite my-react-app --template react-ts

# 进入项目并安装依赖
cd my-react-app
npm install
npm run dev

Vite 项目默认结构:

flowchart TD
    T0["my-react-app/"]
    T1["index.html"]
    T2["package.json"]
    T3["tsconfig.json"]
    T4["vite.config.ts"]
    T5["public/"]
    T6["vite.svg"]
    T7["src/"]
    T8["App.tsx"]
    T9["App.css"]
    T10["main.tsx"]
    T11["index.css"]
    T12["vite-env.d.ts"]
    T0 --> T1
    T0 --> T2
    T0 --> T3
    T0 --> T4
    T0 --> T5
    T6 --> T7
    T7 --> T8
    T7 --> T9
    T7 --> T10
    T7 --> T11
    T7 --> T12

2.2 使用 Next.js 创建项目

Next.js 是 React 全栈框架,支持 SSR、SSG、App Router 等特性。

# 创建 Next.js 15 项目
npx create-next-app@latest my-next-app --typescript --app --tailwind --eslint

# 或使用 pnpm
pnpm create next-app my-next-app --typescript --app --tailwind --eslint

Next.js App Router 项目结构:

flowchart TD
    T0["my-next-app/"]
    T1["next.config.ts"]
    T2["package.json"]
    T3["tsconfig.json"]
    T4["public/"]
    T5["src/"]
    T6["app/"]
    T7["layout.tsx       # 根布局"]
    T8["page.tsx         # 首页"]
    T9["globals.css"]
    T10["favicon.ico"]
    T11["components/"]
    T0 --> T1
    T0 --> T2
    T0 --> T3
    T0 --> T4
    T0 --> T5
    T5 --> T6
    T5 --> T7
    T5 --> T8
    T5 --> T9
    T5 --> T10
    T10 --> T11

2.3 其他全栈框架选择

  • React Router 7(框架模式):Remix 团队已将 Remix 并入 React Router 7(2024 年底发布),作为 React 生态的全栈框架方案继续维护:

    npx create-react-router@latest my-router-app

    注意:独立的 Remix 框架已停止演进,Remix v3 转向了非 React 的技术路线,新项目不建议再选 create-remix。

  • TanStack Start:基于 TanStack Router 的全栈框架,适合偏好类型安全路由与 Vite 生态的团队。

2.4 开发工具配置

VS Code 推荐扩展:

  • ESLint — 代码规范检查
  • Prettier — 代码格式化
  • TypeScript Importer — 自动导入
  • Error Lens — 行内错误提示
  • React Developer Tools — 浏览器调试扩展

推荐 VS Code settings.json 配置:

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "typescript.tsdk": "node_modules/typescript/lib"
}

3. JSX 语法

JSX 是 JavaScript 的语法扩展,允许在 JavaScript 中编写类似 HTML 的代码。自 React 17 起使用自动 JSX 运行时,编译器(Vite/esbuild、Next.js/SWC 等)自动注入 jsx() 调用,组件文件无需再手动 import React。

3.1 基本语法

// JSX 基本结构
const element = <h1>Hello, React 19!</h1>;

// 使用表达式
const name = 'FANDEX';
const greeting = <h1>Hello, {name}!</h1>;

// 调用函数
function formatName(user: { firstName: string; lastName: string }) {
  return `${user.firstName} ${user.lastName}`;
}

const user = { firstName: '张', lastName: '三' };
const element = <h1>Hello, {formatName(user)}!</h1>;

3.2 JSX 属性与样式

// 属性使用 camelCase
const element = (
  <div className="container" htmlFor="input" tabIndex={0}>
    内容
  </div>
);

// 内联样式使用对象
const styleObj: React.CSSProperties = {
  color: 'red',
  fontSize: '16px',
  backgroundColor: '#f0f0f0',
};

const styledElement = <div style={styleObj}>带样式的文本</div>;

3.3 条件渲染

// 三元表达式
const element = isLoggedIn ? <Dashboard /> : <LoginPage />;

// 逻辑与 (&&)
const element = <div>{items.length > 0 && <ItemList items={items} />}</div>;

// 提前返回
function UserGreeting({ name }: { name?: string }) {
  if (!name) {
    return <p>请先登录</p>;
  }
  return <h1>欢迎回来,{name}!</h1>;
}

3.4 列表渲染

const fruits = [
  { id: 1, name: '苹果' },
  { id: 2, name: '香蕉' },
  { id: 3, name: '橙子' },
];

const fruitList = (
  <ul>
    {fruits.map((fruit) => (
      <li key={fruit.id}>{fruit.name}</li>
    ))}
  </ul>
);

注意:key 应使用稳定且唯一的标识符,避免使用数组索引作为 key,尤其在列表会增删时。

4. Hello World

4.1 最简 React 应用

// src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>
);
// src/App.tsx
function App() {
  return (
    <div>
      <h1>Hello, React 19!</h1>
      <p>欢迎使用 FANDEX React 知识库</p>
    </div>
  );
}

export default App;

4.2 客户端渲染 API(React 18 起定型,19 延续)

createRoot 是 React 18 引入、至今仍是唯一的客户端挂载入口,React 19 沿用且未做任何弃用调整:

import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root')!);
root.render(<App />);

需要区分的旧 API:ReactDOM.render(React 17 及以前的挂载方式)在 React 18 起被 createRoot 取代并在 19 中移除;hydrate 同样被 hydrateRoot 取代。若从旧项目迁移,只需替换入口处的挂载调用。

4.3 StrictMode 说明

StrictMode 是开发模式下的辅助工具,它不会渲染任何可见 UI,但会:

  • 识别不安全的生命周期方法
  • 检测过时的 API 用法
  • 检测意外的副作用(组件会被渲染两次)
  • 检测过时的 Context API 用法

提示:StrictMode 的双重渲染仅在开发模式下生效,生产构建中不会触发。

5. TypeScript 与 React

5.1 类型定义

React 的类型定义由独立的 @types/react / @types/react-dom 发布(React 19 对类型做了一次破坏性更新,如 useRef 必须传参、ReactNode 收窄等),安装时注意类型版本要匹配 React 大版本:

npm install react react-dom
npm install -D typescript @types/react @types/react-dom

5.2 常用类型

import type { FC, ReactNode, CSSProperties, ChangeEvent } from 'react';

// 函数组件类型
const MyComponent: FC<{ title: string; children?: ReactNode }> = ({ title, children }) => {
  return (
    <div>
      <h1>{title}</h1>
      {children}
    </div>
  );
};

// 事件类型
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
  console.log(e.target.value);
};

// 样式类型
const styles: CSSProperties = {
  display: 'flex',
  justifyContent: 'center',
};

6. 包管理器选择

包管理器特点推荐场景
npmNode.js 内置,最通用初学者、CI 环境
pnpm硬链接机制,磁盘占用少大型项目、Monorepo
yarn确定性安装,Plug’n’Play团队协作
bun极速安装,内置运行时追求极致性能
# 使用 pnpm(推荐)
corepack enable
corepack prepare pnpm@latest --activate

# 使用 bun
npm install -g bun

应用入口 API

createRoot 创建根容器 const <root> = createRoot(<container>, [<options>]);

import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root')!);
root.render(<App />);

root.render 渲染节点 root.render(<node>);

root.render(<App />);
root.render(null); // 卸载等价

root.unmount 卸载根 root.unmount();

root.unmount();

水合 API

hydrateRoot 服务端 HTML 水合 const <root> = hydrateRoot(<container>, <initialChildren>, [<options>]);

import { hydrateRoot } from 'react-dom/client';
import { App } from './App';

hydrateRoot(document.getElementById('root')!, <App />);

hydrateOptions 水合选项 { onRecoverableError?: <errorHandler>, identifierPrefix?: <string> }

hydrateRoot(container, <App />, {
  onRecoverableError: (error) => console.error(error),
  identifierPrefix: 'app-',
});

严格模式

StrictMode 严格模式组件 <StrictMode>...</StrictMode>

import { StrictMode } from 'react';

createRoot(container).render(
  <StrictMode>
    <App />
  </StrictMode>
);

createRoot 选项

createRoot options { onRecoverableError?: <handler>, identifierPrefix?: <string>, onCaughtError?: <handler>, onUncaughtError?: <handler> }

createRoot(container, {
  onCaughtError: (error, info) => console.warn(error, info.componentStack),
  onUncaughtError: (error) => console.error(error),
  identifierPrefix: 'fandex-',
});

flushSync 同步刷新

flushSync 强制同步刷新 flushSync(<callback>);

import { flushSync } from 'react-dom';

flushSync(() => {
  setCount(c => c + 1);
});