React 项目入门:脚手架、JSX、组件与挂载
本文目录
这篇笔记保留原始归档日期,内容按现代 React 工程整理。React 负责描述和更新 UI;项目脚手架、路由、数据请求、构建和部署则由框架或构建工具提供,不能把它们都当成 React 自带功能。
新项目先选运行模式
面向真实产品:优先评估 React 框架
如果应用需要路由、服务端渲染、静态生成、数据加载、代码拆分或服务端能力,先看 React 官方的框架选择指引。框架通常能把路由、构建和数据约定一起提供,不必自己拼出一套“迷你框架”。选择前核对部署平台、服务端运行时、团队经验和迁移成本。
学习 React 或构建单页应用:可从 Vite 开始
当项目明确是客户端 SPA、已有独立后端,或目的是理解 React 与浏览器的工作方式时,Vite 是轻量的构建工具选择。下面创建 TypeScript 模板;项目不需要 TypeScript 时,把模板名换成 react:
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
npm install
npm run dev
用 Vite 前先对照它的当前指南检查 Node.js 版本要求。模板和工具会持续更新,不要把多年前的 Node/npm 版本号写死在新项目文档里。常用脚本通常包括 dev、build 和 preview;以项目的 package.json 为准。preview 用于本地检查构建结果,不等于生产服务器或正式部署方案。
维护已有 Create React App 项目
Create React App(CRA)仍可用于维护已有项目,但 React 官方已不再推荐用它创建新应用。先识别仓库的 React、Node、构建脚本和部署约束,再按项目需要迁移到框架或 Vite 等构建工具;不要把“换脚手架”当成只改一条命令,路由、环境变量、代理、测试和静态资源路径都要逐项验证。
项目入口和挂载点
一个常见的 Vite + React + TypeScript 项目结构如下。具体目录由模板和团队约定决定:
my-react-app/
├── index.html # HTML 外壳,包含 React 挂载节点
├── package.json # 依赖与项目脚本
├── public/ # 按原路径复制的静态文件
└── src/
├── main.tsx # 浏览器入口,创建 React root
├── App.tsx # 应用根组件
└── assets/ # 需要被构建工具处理的资源
index.html 中的 id="root" 是 DOM 元素的标识,不会自动生成 window.root。浏览器入口通过 document.getElementById 找到这个节点,再用 createRoot 创建 React root:
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
const container = document.getElementById("root");
if (!container) {
throw new Error("Missing #root mount element");
}
createRoot(container).render(
<StrictMode>
<App />
</StrictMode>,
);
createRoot 用于客户端创建并管理一棵 React 树。服务端已输出与客户端匹配的 HTML 时,应按 SSR 框架约定使用 hydrateRoot,不要对同一节点再调用 createRoot 覆盖服务端标记。StrictMode 在开发环境启用额外检查;开发时看到 Effect 多一次 setup/cleanup 检查,不应通过关闭它来掩盖副作用问题。
第一个组件
React 组件通常是以大写字母开头的 JavaScript 函数,返回描述 UI 的 JSX。组件声明在模块顶层,再由父组件组合:
type GreetingProps = {
name: string;
};
function Greeting({ name }: GreetingProps) {
return <p>你好,{name}。</p>;
}
export default function App() {
return (
<main>
<h1>React 入门</h1>
<Greeting name="Haoge" />
</main>
);
}
组件名首字母大写,React 才会把 <Greeting /> 识别为组件;小写标签如 <main> 会被识别为内置 HTML 元素。组件不要在另一个组件函数内部重新定义,否则每次父组件 render 都会创建新的组件类型,可能造成子树状态重置。
JSX 与 HTML 的区别
JSX 是 JavaScript 的语法扩展,不是浏览器原生 HTML,也不等同于 React 本身。构建工具会把 JSX 转换为 JavaScript 调用。常用规则:
- 一个 JSX 表达式返回一个根节点;用 Fragment
<>...</>分组时不会额外增加 DOM 元素。 - 用
{}在 JSX 中嵌入 JavaScript 表达式;不能把任意语句直接塞进花括号。 - DOM 属性多数使用驼峰形式,例如
className、htmlFor、onClick;标准data-*、aria-*属性仍使用连字符形式。 style接收对象,例如style={{ fontSize: 16, color: "teal" }};优先用 CSS 类管理复杂样式。- 列表渲染应提供稳定且与实体对应的
key,避免用可能变化的数组下标充当可重排列表的 key。 - JSX 文本插值会按文本内容渲染。不要把不可信字符串交给
dangerouslySetInnerHTML;确需渲染 HTML 时,必须先用可信的 HTML 清洗策略。
Fragment 可以带 key 的场景需使用显式 <Fragment key={...}>,简写 <>...</> 不能接收属性:
import { Fragment } from "react";
function Names({ names }: { names: string[] }) {
return names.map((name) => (
<Fragment key={name}>
<dt>{name}</dt>
<dd>成员</dd>
</Fragment>
));
}
事件、输入和动态值
事件处理器传函数,而不是在 render 时直接执行它。状态更新规则见状态与 Props 指南;表单值由 React 控制时要保持 value 与 onChange 配套:
import { useState } from "react";
function NameForm() {
const [name, setName] = useState("");
return (
<form onSubmit={(event) => event.preventDefault()}>
<label htmlFor="name">名称</label>
<input
id="name"
value={name}
onChange={(event) => setName(event.currentTarget.value)}
/>
<button type="submit">提交</button>
</form>
);
}
React 会忽略布尔值、null 和 undefined 作为子节点,但数字 0 会显示出来。比如 {items.length && <List />} 在列表为空时会渲染 0;需要布尔判断时写 {items.length > 0 && <List />}。
React、React DOM 与路由的职责
react提供组件、Hooks 和 React 树相关能力。react-dom/client提供浏览器客户端挂载和 hydration API。- 路由库处理 URL 与页面状态的映射;React 本身不内置一个完整的浏览器路由器。参见React Router 指南并核对项目采用的模式和主版本。
- 构建工具负责开发服务器、JSX/TypeScript 转换、资源处理和生产构建;代理配置、环境变量和部署回退通常由工具或宿主平台控制。
旧笔记纠错速查
| 旧说法 | 更准确的理解 |
|---|---|
window.root 就是 HTML 中的 root 节点 | DOM 查询结果需要存进普通变量;React root 是 createRoot(container) 返回的管理对象 |
| JSX 就是 HTML,或 React 就是 JSX | JSX 是语法扩展;React 是 UI 库,两者常配合使用但不是同一个东西 |
| React 只负责逻辑,React DOM 只负责渲染 | react-dom/client 提供浏览器集成 API;React 的组件树同时描述 UI 与交互状态 |
新项目直接运行 npx create-react-app | CRA 已不推荐用于新应用;根据需求选框架,或在适合的客户端项目中选现代构建工具 |
npm start / yarn start 对所有项目都有效 | 命令由仓库脚本决定;先查看 package.json,再使用对应包管理器 |
学习顺序与检查清单
- 先掌握 JavaScript 模块、函数、对象/数组更新、Promise 和浏览器 DOM 基础。
- 学组件、JSX、props、条件/列表渲染和稳定 key。
- 学 state 快照、事件处理、表单与状态提升,再理解 Effect 的适用边界。
- 根据产品需求选择路由、请求缓存、表单和测试工具;不要为了“全家桶”预先装一整套依赖。
- 发布前验证生产构建、直接访问深层路由、刷新行为、静态资源路径、错误态和移动布局。
官方资料
Live Notes
留言提交后会先进入审核,审核通过后对其他读者公开。