← 返回文章列表
4.
React 全指南:从入门到精通
基于费曼学习法、西蒙学习法、SQ3R 阅读法和康奈尔笔记法,系统掌握 React 的核心概念与实战技巧。
一、概览与提问(SQ3R · Survey & Question)
SQ3R 第一步:快速浏览全貌,提出关键问题。
什么是 React?
React 是由 Meta(原 Facebook)开发并开源的 JavaScript UI 库,用于构建 Web 和原生用户界面。自 2013 年发布以来,React 已经成为全球最流行的前端框架之一。React 的核心理念是将 UI 拆分为独立的、可复用的组件(Component),每个组件管理自己的逻辑和外观。
当前最新版本是 React 19.2,引入了 Server Components、React Compiler、use API 等重大特性。React 不是一个大而全的框架——它专注于视图层,与路由、状态管理等库配合使用,形成完整的解决方案。
React 解决的核心问题:
- UI 复杂性管理:通过组件化将复杂的界面拆解为可维护的小单元
- 状态与视图同步:通过声明式编程,开发者只需描述"UI 应该是什么样",React 负责高效更新 DOM
- 跨平台开发:同一套组件模型可以用于 Web(React DOM)和移动端(React Native)
核心问题
- React 适合什么场景?——单页应用、交互密集的 Web 应用、需要跨平台的产品
- React 与同类技术相比有什么优势?——生态成熟、社区庞大、灵活可组合、Meta 持续投入
- 学习 React 需要什么基础?——HTML、CSS、JavaScript(ES6+)、基本的 DOM 知识
技术全景图
React 的技术架构可以概括为以下核心模块的协作:
React 应用
├── 描述 UI(Describing the UI)
│ ├── Components(组件)——UI 的基本构建单元
│ ├── JSX ——声明式标记语法
│ ├── Props ——组件间数据传递
│ └── 条件渲染 & 列表渲染
├── 添加交互性(Adding Interactivity)
│ ├── Events(事件处理)
│ ├── State(状态)——组件的记忆
│ └── Render & Commit(渲染与提交)
├── 状态管理(Managing State)
│ ├── 状态提升(Lifting State Up)
│ ├── Reducer ——复杂状态逻辑
│ ├── Context ——深层数据传递
│ └── Reducer + Context 组合模式
└── 逃逸舱(Escape Hatches)
├── Refs ——引用 DOM 和值
├── Effects ——与外部系统同步
└── Custom Hooks ——逻辑复用
二、用最简单的话说清楚(费曼学习法)
费曼学习法核心理念:如果你不能用简单的语言解释一件事,说明你还没有真正理解它。
核心概念讲解
组件(Component)
组件就是 JavaScript 函数,返回你想要看到的界面。一个组件可以小到一个按钮,大到整个页面。
function MyButton() {
return <button>I'm a button</button>;
}
// 在另一个组件中使用
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}注意:组件名必须以大写字母开头(MyButton),HTML 标签用小写(button)。
JSX
JSX 是一种在 JavaScript 中写 HTML 的语法。它比 HTML 更严格:标签必须闭合(如 <br />),组件不能返回多个根标签,需要用 <div> 或 <>...</> 包裹。
function AboutPage() {
return (
<>
<h1>About</h1>
<p>
Hello there.
<br />
How do you do?
</p>
</>
);
}用花括号 {} 可以在 JSX 中嵌入 JavaScript 表达式:
const user = { name: "Hedy Lamarr" };
return <h1>{user.name}</h1>;Props(属性)
Props 是父组件传递给子组件的数据,就像函数的参数。
function MyButton({ count, onClick }) {
return <button onClick={onClick}>Clicked {count} times</button>;
}
// 父组件传递 props
<MyButton count={count} onClick={handleClick} />;State(状态)
State 是组件的"记忆"。用 useState Hook 声明一个状态变量。
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Clicked {count} times</button>;
}useState 返回两个值:当前状态值(count)和更新函数(setCount)。每次调用 setCount,React 会重新渲染组件。
事件处理
事件处理函数在组件内部定义,通过 onEventName 属性绑定。
function MyButton() {
function handleClick() {
alert("You clicked me!");
}
return <button onClick={handleClick}>Click me</button>;
}注意:onClick={handleClick} 末尾没有括号——你传递的是函数本身,不是调用结果。React 会在用户点击时调用它。
条件渲染
React 没有特殊的条件语法,直接使用 JavaScript:
// if...else
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return <div>{content}</div>;
// 三元表达式(可以在 JSX 中使用)
<div>{isLoggedIn ? <AdminPanel /> : <LoginForm />}</div>
// 逻辑与(不需要 else 分支时)
<div>{isLoggedIn && <AdminPanel />}</div>列表渲染
使用 JavaScript 的 map() 函数渲染列表,每个列表项需要唯一的 key:
const products = [
{ title: "Cabbage", id: 1 },
{ title: "Garlic", id: 2 },
{ title: "Apple", id: 3 },
];
const listItems = products.map((product) => <li key={product.id}>{product.title}</li>);
return <ul>{listItems}</ul>;key 帮助 React 识别列表中哪些项发生了变化(插入、删除、重排)。
类比与比喻
- 组件 = 乐高积木:每块积木有独立的形状和功能,可以自由组合拼装成更大的作品。一个按钮是一块积木,一个页面是许多积木的组合。
- Props = 快递包裹:父组件通过 props 给子组件"寄包裹"。子组件收到包裹后使用里面的东西,但不能自己修改包裹内容。
- State = 组件的记事本:每个组件有自己的小本子,用来记录会变化的信息。本子上的内容变了,界面就自动更新。
- JSX = HTML 的超集:就像在 HTML 里可以直接写 JavaScript 一样,用花括号
{}把 JavaScript "嵌入"到标记语言中。 - Hooks = 插件接口:Hooks 就像 USB 接口,让你把 React 的各种能力(状态管理、副作用、引用)"插"到组件里。
- Context = 室内广播:如果说 Props 是快递员一层层递送包裹,那 Context 就像房间里的广播——顶层组件广播一条消息,下面任何层级的组件都能听到。
常见误解澄清
- "React 是一个 MVC 框架"——不是。React 只是 V(视图层)。路由、数据获取等需要其他库配合。
- "JSX 就是 HTML"——不是。JSX 是 JavaScript 的语法扩展,更严格(标签必须闭合、
className代替class)。 - "State 变了 DOM 就立刻更新"——不是。React 会批量处理状态更新,在合适的时机统一更新 DOM。
- "每次渲染都会重建所有 DOM"——不是。React 通过 Virtual DOM 进行 diff 算法比较,只更新实际变化的部分。
- "Hooks 可以在 if/for 中调用"——不可以。Hooks 必须在组件顶层调用,不能放在条件语句、循环或嵌套函数中。
- "useEffect 就是 Vue 的 watch"——不完全正确。useEffect 是在渲染提交到屏幕之后运行的,用于与外部系统同步,不是简单的数据监听器。
- "Context 可以替代所有状态管理"——不可以。Context 适合"远距离"传递数据,但滥用会导致不必要的重渲染。
三、锥形深入(西蒙学习法)
西蒙学习法:集中精力、目标导向、锥形深入——从核心开始,逐步扩展到周边。
第一层:核心基础
1. useState —— 状态管理
useState 是最基础的 Hook,为组件添加"记忆"。
import { useState } from "react";
function Form() {
const [firstName, setFirstName] = useState("Mary");
const [lastName, setLastName] = useState("Poppins");
function handleFirstNameChange(e) {
setFirstName(e.target.value);
}
return (
<>
<label>
First name:
<input value={firstName} onChange={handleFirstNameChange} />
</label>
<p>
<b>
Good morning, {firstName} {lastName}.
</b>
</p>
</>
);
}要点:
useState(initialValue)返回[state, setState]- 调用
setState会触发重新渲染 - 状态更新可能是异步的,使用函数式更新保证基于最新值:
setCount(c => c + 1)
2. useEffect —— 副作用处理
useEffect 用于在渲染之后与外部系统同步。
import { useEffect, useRef } from "react";
function VideoPlayer({ src, isPlaying }) {
const ref = useRef(null);
useEffect(() => {
if (isPlaying) {
ref.current.play();
} else {
ref.current.pause();
}
}, [isPlaying]); // 只在 isPlaying 变化时重新运行
return <video ref={ref} src={src} loop playsInline />;
}三步写 Effect:
- 声明 Effect(
useEffect(() => { ... })) - 指定依赖数组(
[dep1, dep2]) - 如有需要,添加清理函数(
return () => { ... })
3. Props 与状态提升
当多个组件需要共享状态时,将状态提升到它们的最近公共父组件。
import { useState } from "react";
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
return <button onClick={onClick}>Clicked {count} times</button>;
}4. useRef —— 引用值
useRef 用于保存不触发重新渲染的值,或引用 DOM 元素。
import { useRef } from "react";
function MyInput({ value, onChange }) {
const ref = useRef(null);
function focusInput() {
ref.current.focus();
}
return <input ref={ref} value={value} onChange={onChange} />;
}与 useState 的区别:修改 ref.current 不会触发重新渲染。
5. 事件处理
function Form() {
function handleSubmit(e) {
e.preventDefault();
console.log("Form submitted");
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}6. 条件渲染与列表渲染
function ProductList({ products, filterText, inStockOnly }) {
const rows = [];
let lastCategory = null;
products.forEach((product) => {
// 过滤逻辑
if (product.name.toLowerCase().indexOf(filterText.toLowerCase()) === -1) {
return;
}
if (inStockOnly && !product.stocked) {
return;
}
// 条件渲染分类标题
if (product.category !== lastCategory) {
rows.push(<ProductCategoryRow category={product.category} key={product.category} />);
}
rows.push(<ProductRow product={product} key={product.name} />);
lastCategory = product.category;
});
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}7. 更新对象和数组
React 中状态是不可变的,必须创建新的对象/数组来触发更新。
import { useState } from "react";
function TodoList() {
const [todos, setTodos] = useState([]);
const [text, setText] = useState("");
function addTodo() {
// 创建新数组,而非修改原数组
setTodos([...todos, text]);
setText("");
}
function removeTodo(index) {
setTodos(todos.filter((_, i) => i !== index));
}
return (
<>
<input value={text} onChange={(e) => setText(e.target.value)} />
<button onClick={addTodo}>Add</button>
<ul>
{todos.map((todo, i) => (
<li key={i}>
{todo}
<button onClick={() => removeTodo(i)}>Delete</button>
</li>
))}
</ul>
</>
);
}第二层:进阶用法
1. useContext —— 深层数据传递
Context 解决了"prop drilling"问题——无需层层传递 props。
// 1. 创建 Context
import { createContext, useContext } from "react";
const LevelContext = createContext(1);
// 2. 在子组件中使用
function Heading({ children }) {
const level = useContext(LevelContext);
const Tag = `h${level}`;
return <Tag>{children}</Tag>;
}
// 3. 在父组件中提供
function Section({ level, children }) {
return <LevelContext value={level}>{children}</LevelContext>;
}
// 使用:Section 自动传递 level 给所有嵌套的 Heading
function Page() {
return (
<Section level={1}>
<Heading>Title</Heading>
<Section level={2}>
<Heading>Heading</Heading>
<Heading>Heading</Heading>
</Section>
</Section>
);
}典型应用场景:主题切换、当前用户、国际化语言设置、路由信息。
2. useReducer —— 复杂状态逻辑
当状态逻辑复杂时,useReducer 比 useState 更清晰。
import { useReducer } from "react";
function reducer(state, action) {
switch (action.type) {
case "incremented":
return { count: state.count + 1 };
case "decremented":
return { count: state.count - 1 };
default:
throw new Error("Unknown action: " + action.type);
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
<button onClick={() => dispatch({ type: "decremented" })}>-</button>
{state.count}
<button onClick={() => dispatch({ type: "incremented" })}>+</button>
</>
);
}3. useCallback 与 useMemo —— 性能优化
import { useState, useCallback, useMemo } from "react";
function ProductPage({ products }) {
const [filterText, setFilterText] = useState("");
const [isLarge, setIsLarge] = useState(false);
// useMemo:缓存计算结果
const filteredProducts = useMemo(() => {
return products.filter((p) => p.name.toLowerCase().includes(filterText.toLowerCase()));
}, [products, filterText]);
// useCallback:缓存函数引用
const handleFilterChange = useCallback((e) => {
setFilterText(e.target.value);
}, []);
return (
<>
<input value={filterText} onChange={handleFilterChange} />
<ProductList products={filteredProducts} />
</>
);
}注意:不要过度使用。React 19 配合 React Compiler 可以自动处理大部分优化。
4. 自定义 Hook
自定义 Hook 用于在组件间复用有状态逻辑。
// useOnlineStatus.js
import { useState, useEffect } from "react";
export function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
function handleOnline() {
setIsOnline(true);
}
function handleOffline() {
setIsOnline(false);
}
window.addEventListener("online", handleOnline);
window.addEventListener("offline", handleOffline);
return () => {
window.removeEventListener("online", handleOnline);
window.removeEventListener("offline", handleOffline);
};
}, []);
return isOnline;
}
// 在多个组件中使用
function StatusBar() {
const isOnline = useOnlineStatus();
return <h1>{isOnline ? "Online" : "Disconnected"}</h1>;
}
function SaveButton() {
const isOnline = useOnlineStatus();
return <button disabled={!isOnline}>{isOnline ? "Save progress" : "Reconnecting..."}</button>;
}命名规则:自定义 Hook 必须以 use 开头(如 useOnlineStatus),这样 React 的 lint 规则才能正确检查其使用方式。
5. Effect 的正确使用模式
Effect 用于与外部系统同步,不是用来响应状态变化的通用工具。
// 正确:连接到聊天服务器
function ChatRoom({ roomId }) {
useEffect(() => {
const connection = createConnection(roomId);
connection.connect();
return () => connection.disconnect(); // 清理函数
}, [roomId]); // 只在 roomId 变化时重连
}
// 错误:不需要 Effect 来根据其他 state 计算 state
// 错误做法:
useEffect(() => {
setFullName(firstName + " " + lastName);
}, [firstName, lastName]);
// 正确做法:直接在渲染时计算
const fullName = firstName + " " + lastName;Effect 清理的关键模式:
- 事件订阅 →
addEventListener/removeEventListener - 数据获取 → 设置
ignore标志忽略过时响应 - 动画 → 重置到初始值
- 定时器 →
setTimeout/clearTimeout
第三层:深度解析
1. 渲染机制:Render & Commit
React 更新 UI 的过程分三步:
- 触发渲染(Trigger):调用
setState或首次渲染 - 渲染(Render):React 调用组件函数,计算新的 JSX(Virtual DOM)
- 提交(Commit):React 将变化应用到真实 DOM
State 是快照:每次渲染都有自己固定的 state 值。事件处理函数和 Effect 中捕获的 state 值属于那次渲染,不会改变。
function Counter() {
const [count, setCount] = useState(0);
function handleAlertClick() {
setTimeout(() => {
alert("You clicked on: " + count); // 显示的是点击时的 count,不是当前的
}, 3000);
}
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={handleAlertClick}>Show alert</button>
</div>
);
}2. 状态更新的批处理与队列
React 会批量处理状态更新。同一事件处理函数中的多个 setState 只会触发一次渲染。
function handleClick() {
setCount(count + 1); // 此时 count 还是旧值
setCount(count + 1); // 还是基于旧值,结果只 +1
}
// 正确做法:使用函数式更新
function handleClick() {
setCount((c) => c + 1); // c 是最新的待处理值
setCount((c) => c + 1); // 基于上一个更新,结果 +2
}3. React 编译器(React Compiler)
React 19 引入了 React Compiler,这是一个构建时优化工具,自动对组件和值进行 memoization:
- 自动识别需要缓存计算的地方
- 减少
useMemo和useCallback的手动使用 - 可以渐进式采用,与现有代码兼容
- 通过
@babel/plugin-transform-react-compiler集成
4. use API
React 19 新增的 use API 可以在渲染期间读取 Promise 和 Context:
import { use, Suspense } from "react";
function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Here is the message: {messageContent}</p>;
}
export function MessageContainer({ messagePromise }) {
return (
<Suspense fallback={<p>Downloading message...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}5. Thinking in React —— React 思维方式
构建 React 应用的五个步骤:
- 将 UI 拆分为组件层级:根据数据模型和设计稿划分组件
- 构建静态版本:先不考虑交互,用 props 传递数据构建 UI
- 确定最小状态集合:遵循 DRY 原则,找出真正需要的状态
- 确定状态的位置:将状态放在使用它的组件的最近公共父组件中
- 添加反向数据流:子组件通过回调函数更新父组件的状态
6. Reducer + Context 组合模式
这是 React 管理复杂应用状态的模式:
import { createContext, useContext, useReducer } from "react";
// 1. 创建 Context
const TasksContext = createContext(null);
const TasksDispatchContext = createContext(null);
// 2. 定义 Reducer
function tasksReducer(tasks, action) {
switch (action.type) {
case "added":
return [...tasks, { id: action.id, text: action.text }];
case "deleted":
return tasks.filter((t) => t.id !== action.id);
default:
throw new Error("Unknown action: " + action.type);
}
}
// 3. Provider 组件
export function TasksProvider({ children }) {
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
return (
<TasksContext value={tasks}>
<TasksDispatchContext value={dispatch}>{children}</TasksDispatchContext>
</TasksContext>
);
}
// 4. 自定义 Hook 供子组件使用
export function useTasks() {
return useContext(TasksContext);
}
export function useTasksDispatch() {
return useContext(TasksDispatchContext);
}7. 组件纯净性与 Rules of React
React 有三条核心规则:
- 组件和 Hook 必须是纯函数:相同的输入产生相同的输出,不产生副作用
- React 负责调用组件和 Hook:不要手动调用组件函数
- Hook 的使用规则:只在组件或 Hook 的顶层调用,不能在条件语句或循环中调用
四、要点笔记(康奈尔笔记法)
康奈尔笔记法:将笔记分为线索栏、笔记栏和总结栏,便于复习和检索。
关键概念速查表
| 线索/关键词 | 详细笔记 |
|---|---|
| Component | 返回 JSX 的 JavaScript 函数,名称大写开头 |
| JSX | JavaScript 的标记语法扩展,用花括号嵌入表达式 |
| Props | 父传子的只读数据,类似函数参数 |
| State | 组件内部的可变数据,用 useState 声明 |
| Hooks | 以 use 开头的函数,只能在组件顶层调用 |
| Virtual DOM | React 内部的轻量级 DOM 表示,用于 diff 计算 |
| Re-render | state/props 变化时组件函数重新执行 |
| Render & Commit | 触发 -> 计算 JSX -> 应用到真实 DOM |
| State Snapshot | 每次渲染的 state 值固定不变 |
| Lifting State Up | 将共享状态移到最近公共父组件 |
| Effect | 渲染后执行,用于与外部系统同步 |
| Cleanup | Effect 返回的清理函数,在下次 Effect 运行前和卸载时调用 |
| Context | 父组件向任意深度的子组件传递数据 |
| Reducer | 用 dispatch(action) 管理复杂状态逻辑 |
| Custom Hook | 以 use 开头的自定义函数,复用有状态逻辑 |
| Key | 列表渲染中的唯一标识,帮助 React 追踪元素 |
| React Compiler | 构建时自动 memoization 的优化工具 |
use API | React 19 新增,在渲染中读取 Promise/Context |
核心 API 速查
| API / Hook | 用途 | 示例 |
|---|---|---|
useState | 声明状态变量 | const [val, setVal] = useState(0) |
useEffect | 渲染后执行副作用 | useEffect(() => { ... }, [dep]) |
useRef | 引用 DOM 或保存不触发渲染的值 | const ref = useRef(null) |
useContext | 读取 Context 值 | const value = useContext(MyContext) |
useReducer | 复杂状态管理 | const [state, dispatch] = useReducer(reducer, init) |
useCallback | 缓存函数引用 | const fn = useCallback(() => {}, [deps]) |
useMemo | 缓存计算结果 | const val = useMemo(() => compute(a), [a]) |
createContext | 创建 Context | const Ctx = createContext(defaultValue) |
use | 在渲染中读取 Promise | const data = use(promise) |
useSyncExternalStore | 订阅外部数据源 | const val = useSyncExternalStore(subscribe, getSnapshot) |
useEffectEvent | Effect 中的事件处理器(不加入依赖) | const onMsg = useEffectEvent(handler) |
本节总结
React 的核心思想是组件化和声明式 UI。组件通过 Props 接收数据、通过 State 管理内部状态、通过 Context 进行远距离数据传递。Hooks(useState、useEffect、useRef 等)是组件与 React 能力交互的唯一入口。Effect 用于与外部系统同步,自定义 Hook 用于复用有状态逻辑。React 19 的 React Compiler 和 use API 代表了框架的发展方向——更少的样板代码,更自动化的优化。
五、复习与实践(SQ3R · Recite & Review)
SQ3R 最后两步:复述核心要点,通过实践巩固理解。
核心要点回顾
- React 组件是返回 JSX 的 JavaScript 函数,组件名必须大写开头
- JSX 中用花括号
{}嵌入 JavaScript 表达式 - Props 是父传子的只读数据流,State 是组件内部的可变状态
useState返回[value, setter],调用 setter 触发重新渲染- 状态提升(Lifting State Up)是共享组件状态的标准模式
- 列表渲染必须使用唯一的
key属性 useEffect用于与外部系统同步,必须指定依赖数组- Effect 需要清理函数来防止资源泄漏(订阅、连接、定时器)
- Context 解决 prop drilling 问题,但不应该替代所有状态传递
- 自定义 Hook 以
use开头,用于在组件间复用有状态逻辑 useReducer适合复杂状态逻辑,配合 Context 可形成全局状态管理方案- React 19 的 React Compiler 自动处理 memoization,减少手动优化
- 渲染过程:Trigger -> Render(计算 JSX)-> Commit(更新 DOM)
- State 在每次渲染中是固定的快照,闭包捕获的是当时渲染的值
- React 的三条规则:组件纯净、React 控制调用、Hook 规则
动手练习
-
静态个人名片页:创建一个包含头像、姓名、简介的组件。练习组件创建、Props 传递和 JSX 基础。
-
可搜索的产品列表:按照 "Thinking in React" 教程,实现一个带搜索过滤和库存筛选的产品表格。练习状态提升、条件渲染和列表渲染。
-
聊天室应用:创建一个连接到模拟服务器的聊天组件。练习
useEffect的声明、依赖数组和清理函数。 -
主题切换系统:用 Context 实现明/暗主题切换,让所有嵌套组件自动适配。练习
createContext、useContext和 Provider。 -
任务管理系统:用 Reducer + Context 模式实现一个 Todo 应用,支持添加、删除、标记完成。练习
useReducer、自定义 Hook 和 Context 组合。
常见陷阱
-
忘记依赖数组:
useEffect不传依赖数组会在每次渲染后运行,可能导致无限循环// 错误:无限循环 useEffect(() => { setCount(count + 1); }); // 正确:明确依赖 useEffect(() => { setCount((c) => c + 1); }, []); -
直接修改状态对象:必须创建新对象/数组
// 错误 state.items.push(newItem); setState(state); // 正确 setState({ ...state, items: [...state.items, newItem] }); -
在 Effect 中做不该做的事:购买商品、提交表单等用户触发的操作应该放在事件处理器中,不是 Effect
-
使用索引作为 key:在列表会重排、插入、删除时,用索引作 key 会导致渲染错误。应使用稳定的唯一 ID
-
过度使用 Context:Context 值变化时所有消费者都会重渲染。对于高频变化的数据,考虑使用状态管理库或将状态限定在更小的范围内
延伸阅读
- React 官方文档——最权威的学习资源
- React 19 发布说明——了解最新特性
- React Compiler 指南——自动优化机制
- Rules of React——React 的编程范式规则
- React TypeScript Cheatsheet——TypeScript 与 React 结合的实用指南