文章目录

React 基础学习笔记

适合目标:系统掌握 React 基础开发能力,并能回答常见面试题。
学习定位:这一份偏“会用、会答、会优化”,适合先建立 React 使用层的完整知识体系。
学习原则:先理解 React 的思维方式,再记 API;先会写组件,再讲优化;先能解释业务场景,再背面试答案。


目录

  1. 学习总览
  2. React 的核心思维
  3. JSX 与组件基础
  4. Props、State 与渲染
  5. 事件、表单与列表渲染
  6. 生命周期思维与函数组件时代
  7. Hooks 全家桶
  8. 组件通信
  9. 状态管理选型
  10. React 18 高频知识点
  11. 性能优化手段
  12. 高频面试题
  13. 6 小时学习规划
  14. 一页速记总结
  15. 背诵口诀

1. 学习总览

1.1 React 到底在解决什么问题

React 不是一个“页面模板语言”,它本质上是在帮我们解决这几个问题:

  1. 界面如何拆成可复用组件
  2. 状态变化后,界面如何自动更新
  3. 多个组件之间,数据如何流动
  4. 当页面变复杂时,如何保持可维护性

你可以把 React 理解成:

UI = f(state)

意思是:

  1. 界面是状态的映射
  2. 状态变了,界面就重新计算
  3. 我们重点维护“状态”和“组件结构”,DOM 更新交给 React

1.2 学 React 要先建立的三条主线

主线 1:组件化

把一个页面拆成多个独立的、可组合的组件。

主线 2:数据驱动视图

不是手动改 DOM,而是修改状态,让 React 帮你更新视图。

主线 3:单向数据流

父组件通过 props 向下传递数据,状态提升和回调函数负责交互。

1.3 React 学习顺序

建议按这个顺序建立体系:

  1. JSX 和组件
  2. props 和 state
  3. 事件、列表、条件渲染
  4. Hooks
  5. 组件通信
  6. React 18 特性
  7. 性能优化
  8. 状态管理

2. React 的核心思维

2.1 声明式 UI

React 是声明式的,不是命令式的。

命令式思维

你需要自己一步一步操作 DOM:

  1. 找到节点
  2. 修改文本
  3. 添加 class
  4. 控制显示隐藏

声明式思维

你只需要表达:

当前状态下,界面应该长什么样

React 会根据新旧状态,帮你把 DOM 更新到正确结果。

示例:

function Counter() {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <p>当前计数:{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

2.2 组件化思维

React 项目里,一个页面通常会拆成:

  1. 页面组件
  2. 业务组件
  3. 通用组件
  4. 布局组件
  5. 纯展示组件

拆分标准可以记成三点:

  1. 是否可复用
  2. 是否职责独立
  3. 是否会单独变化

2.3 单向数据流

React 里最重要的思想之一就是:

数据通常从父到子流动

父组件:

  1. 持有状态
  2. 通过 props 传给子组件
  3. 通过回调让子组件通知父组件

示例:

function Parent() {
  const [count, setCount] = React.useState(0);

  return <Child count={count} onAdd={() => setCount((c) => c + 1)} />;
}

function Child({ count, onAdd }) {
  return <button onClick={onAdd}>当前值:{count}</button>;
}

2.4 React 中最重要的两个词

Render

根据当前状态计算出应该渲染什么 UI。

Re-render

状态变了,组件重新执行,生成新的虚拟结构。

注意:

  1. 重新渲染不等于 DOM 一定重建
  2. React 会比较新旧结果,再决定最小化更新

2.5 记忆口诀

React 不直接教你改页面,而是让你描述状态下的页面。


3. JSX 与组件基础

3.1 JSX 是什么

JSX 是 JavaScript 的语法扩展,看起来像 HTML,但本质不是字符串模板,而是会被编译成 React 元素对象。

const element = <h1>Hello React</h1>;

会被转换成类似:

const element = React.createElement("h1", null, "Hello React");

3.2 JSX 的核心规则

  1. 必须有一个根节点
  2. 标签必须闭合
  3. 使用驼峰命名属性,如 classNameonClick
  4. 在 JSX 中插入 JS 表达式要用 {} 包裹

示例:

function App() {
  const name = "Tom";
  return <div className="app">Hello, {name}</div>;
}

3.3 JSX 里能放什么

{} 中可以放:

  1. 变量
  2. 表达式
  3. 三元表达式
  4. 函数调用结果
  5. 数组映射结果

不能直接放:

  1. if 语句
  2. for 语句
  3. 普通对象本身

3.4 组件是什么

组件就是返回 UI 描述的函数。

function Welcome() {
  return <h1>Hello</h1>;
}

组件名必须大写开头,否则会被当成原生标签。

3.5 组件的分类

函数组件

现代 React 开发主流。

function Button() {
  return <button>按钮</button>;
}

类组件

现在仍需理解,但日常新项目基本以函数组件为主。

class Button extends React.Component {
  render() {
    return <button>按钮</button>;
  }
}

3.6 props 是什么

props 是组件的输入参数,用于父组件向子组件传值。

function UserCard(props) {
  return <div>{props.name}</div>;
}

更常见写法:

function UserCard({ name, age }) {
  return (
    <div>
      <p>{name}</p>
      <p>{age}</p>
    </div>
  );
}

3.7 children 是什么

children 是组件标签内部的内容。

function Card({ children }) {
  return <div className="card">{children}</div>;
}

function App() {
  return <Card><h2>标题</h2></Card>;
}

3.8 条件渲染

常见方式:

  1. 三元表达式
  2. &&
  3. 提前 return
function UserInfo({ isLogin }) {
  if (!isLogin) return <p>请登录</p>;
  return <p>欢迎回来</p>;
}

3.9 列表渲染

React 中渲染列表通常用 map

function TodoList({ list }) {
  return (
    <ul>
      {list.map((item) => (
        <li key={item.id}>{item.text}</li>
      ))}
    </ul>
  );
}

3.10 key 为什么重要

key 是 React 在同层节点中识别元素身份的重要标记。

作用:

  1. 帮助 React 复用节点
  2. 减少不必要更新
  3. 保持列表项状态稳定

不要乱用 index 的场景:

  1. 列表有插入、删除、排序
  2. 列表项内部有本地状态

3.11 JSX 与组件记忆口诀

JSX 是语法糖,组件是函数,props 是输入,children 是插槽。


4. Props、State 与渲染

4.1 state 是什么

state 是组件内部可变化的数据。

React 中状态变化会触发重新渲染。

function Counter() {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

4.2 props 和 state 的区别

对比项 props state
来源 父组件传入 组件内部维护
是否可直接修改 不应该 通过更新函数修改
作用 组件输入 组件自身状态

4.3 React 中一次状态更新发生了什么

可以先这样理解:

  1. 调用 setState / setCount
  2. React 记录这次更新
  3. 组件重新执行
  4. 生成新的虚拟 UI
  5. React 比较新旧结果
  6. 只更新有变化的部分

4.4 为什么 state 更新后不是立刻拿到新值

这类题很高频。

示例:

function App() {
  const [count, setCount] = React.useState(0);

  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // 旧值
  };

  return <button onClick={handleClick}>点击</button>;
}

原因:

  1. React 状态更新是异步调度的
  2. 当前函数执行时,拿到的是本次渲染闭包中的旧值
  3. 重新渲染后,组件才会拿到新状态

4.5 为什么连续 setCount(count + 1) 可能只加 1

setCount(count + 1);
setCount(count + 1);

因为两次都基于同一个旧 count

正确写法:

setCount((c) => c + 1);
setCount((c) => c + 1);

函数式更新适合:

  1. 新状态依赖旧状态
  2. 同一轮里可能连续触发多次更新

4.6 不可变更新为什么重要

React 依赖引用变化判断很多更新场景,因此更新对象和数组时不要直接修改原数据。

错误写法:

user.name = "Jack";
setUser(user);

推荐写法:

setUser((prev) => ({ ...prev, name: "Jack" }));

4.7 派生状态要谨慎

很多初学者喜欢把“可由现有状态计算出来的值”也放进 state。

例如:

const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const fullName = `${firstName} ${lastName}`;

这里 fullName 没必要单独再放一个 state。

原则:

能算出来的,就不要重复存。

4.8 记忆口诀

props 是输入,state 是内部可变数据,更新状态要用新引用。


5. 事件、表单与列表渲染

5.1 React 事件是什么

React 事件写法和原生事件类似,但使用驼峰命名:

function App() {
  const handleClick = () => {
    console.log("clicked");
  };

  return <button onClick={handleClick}>点击</button>;
}

5.2 事件处理的常见写法

写法 1:直接传函数

<button onClick={handleClick}>点击</button>

写法 2:内联箭头函数

<button onClick={() => handleDelete(id)}>删除</button>

5.3 不要在渲染时直接执行函数

错误写法:

<button onClick={handleClick()}>点击</button>

这会在渲染阶段立刻执行。

5.4 受控组件

表单值由 React state 控制,就是受控组件。

function Form() {
  const [value, setValue] = React.useState("");

  return (
    <input
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}

优点:

  1. 数据源统一
  2. 方便校验
  3. 方便联动

5.5 非受控组件

表单值主要由 DOM 自己保存,通过 ref 获取,就是非受控组件。

function Form() {
  const inputRef = React.useRef(null);

  const handleSubmit = () => {
    console.log(inputRef.current.value);
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleSubmit}>提交</button>
    </>
  );
}

5.6 受控和非受控怎么选

大部分业务表单优先受控组件,因为:

  1. 更符合 React 数据流
  2. 更容易做校验和联动
  3. 更容易和表单库配合

5.7 列表渲染常见坑

坑 1:用 index 作为 key

如果列表顺序变化,可能导致:

  1. 节点错误复用
  2. 输入框状态错位
  3. 动画错乱

坑 2:在 render 中做太重的计算

如果每次渲染都对大列表做复杂计算,会影响性能。

可以考虑:

  1. 预处理数据
  2. useMemo
  3. 虚拟列表

5.8 记忆口诀

表单优先受控,列表重视 key,事件传函数别提前执行。


6. 生命周期思维与函数组件时代

6.1 类组件生命周期先建立理解

虽然现代 React 主流是 Hooks,但面试中依然常把 Hooks 和生命周期对比着问。

类组件常见生命周期:

  1. 挂载:constructorrendercomponentDidMount
  2. 更新:rendercomponentDidUpdate
  3. 卸载:componentWillUnmount

6.2 函数组件没有传统生命周期方法

函数组件不是没有生命周期,而是换了一种理解方式:

  1. 每次渲染都是一次新的函数执行
  2. useEffect 用来处理副作用和清理
  3. 渲染结果由当前 props 和 state 决定

6.3 如何理解 useEffect 对应生命周期

可以粗略类比:

  1. useEffect(() => {}, []) 类似挂载后执行一次
  2. useEffect(() => {}, [dep]) 类似依赖变化后执行
  3. return () => {} 类似卸载前清理

但要注意:

useEffect 不是对生命周期的一一翻译,它更准确地说是“渲染后同步外部系统”。`

6.4 React 中副作用是什么

副作用就是那些不属于“纯渲染计算”的事情,比如:

  1. 请求数据
  2. 订阅事件
  3. 操作 DOM
  4. 定时器
  5. 手动修改标题

6.5 StrictMode 下 effect 为什么执行两次

开发环境下,React 严格模式会帮助你发现副作用问题,因此某些逻辑会出现“额外调用”。

常见表现:

  1. effect 执行两次
  2. 初始化逻辑跑两次

这通常只发生在开发模式,不代表生产环境也会双执行。

6.6 记忆口诀

类组件记生命周期,函数组件记渲染 + effect + 清理。


7. Hooks 全家桶

Hooks 是 React 基础中的核心,也是面试重点。

7.1 Hooks 总规则

规则 1:只在函数组件或自定义 Hook 中调用

规则 2:只在顶层调用,不要在条件、循环、嵌套函数里调用

原因:

React 依赖 Hook 调用顺序来匹配内部状态。


7.2 useState

作用

给函数组件添加状态。

const [count, setCount] = React.useState(0);

关键点

  1. 初始值只在首次渲染使用
  2. 更新状态会触发重新渲染
  3. 更新是异步调度的
  4. 新状态依赖旧状态时用函数式更新

惰性初始化

const [count, setCount] = React.useState(() => {
  return Number(localStorage.getItem("count") || 0);
});

适合初始化成本较高的场景。

常见面试题

为什么 useState 不能条件调用?

答:

因为 React 需要依赖固定调用顺序,把每次渲染中的 Hook 和对应状态槽位一一匹配。


7.3 useEffect

作用

处理副作用。

useEffect(() => {
  document.title = `count: ${count}`;
}, [count]);

依赖数组怎么理解

依赖数组表示:

effect 使用了哪些会变化的外部值

三种常见写法

不传依赖数组

每次渲染后都执行。

useEffect(() => {
  console.log("每次渲染后执行");
});
传空数组

只在挂载后执行一次。

useEffect(() => {
  console.log("仅首次执行");
}, []);
传具体依赖

依赖变化后重新执行。

useEffect(() => {
  console.log("count 变化后执行");
}, [count]);

清理函数

useEffect(() => {
  const timer = setInterval(() => {
    console.log("tick");
  }, 1000);

  return () => {
    clearInterval(timer);
  };
}, []);

清理场景:

  1. 定时器
  2. 事件监听
  3. 订阅
  4. 网络请求中断

useEffect 常见误区

误区 1:把它当生命周期翻译器

本质应该理解成:渲染后同步外部系统。

误区 2:依赖项不写全

这会产生闭包陈旧值问题。

误区 3:effect 里堆太多逻辑

建议按关注点拆分多个 effect。


7.4 useRef

作用 1:拿 DOM 节点

function App() {
  const inputRef = React.useRef(null);

  return <input ref={inputRef} />;
}

作用 2:保存不会触发重渲染的可变值

const timerRef = React.useRef(null);

useRef 和 useState 的区别

对比项 useRef useState
值变化是否触发渲染 不会
常见用途 DOM、缓存实例、定时器 ID 驱动界面更新的数据

7.5 useMemo

作用

缓存计算结果,避免重复执行昂贵计算。

const total = useMemo(() => {
  return list.reduce((sum, item) => sum + item.price, 0);
}, [list]);

适合场景

  1. 计算量大
  2. 结果复用明显
  3. 依赖变化相对少

注意:

不要为了“看起来高级”到处加 useMemo

7.6 useCallback

作用

缓存函数引用。

const handleClick = useCallback(() => {
  console.log("click");
}, []);

什么时候有意义

  1. 函数传给被 React.memo 包裹的子组件
  2. 作为某些 Hook 依赖,且你需要稳定引用

useMemo 和 useCallback 区别

  1. useMemo 缓存值
  2. useCallback 缓存函数

可以简单记成:

useMemo(fn, deps) => 缓存 fn 的返回值
useCallback(fn, deps) => 缓存 fn 本身

7.7 useContext

作用

跨层级传值,避免一层层透传 props。

const ThemeContext = React.createContext("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Page />
    </ThemeContext.Provider>
  );
}

function Page() {
  const theme = React.useContext(ThemeContext);
  return <div>{theme}</div>;
}

适合场景

  1. 主题
  2. 用户信息
  3. 国际化
  4. 小中型共享状态

注意点

Context 不是万能状态管理。

如果 value 频繁变化且范围很大,可能导致不必要重渲染。

7.8 useReducer

作用

适合较复杂、规则明确的状态更新逻辑。

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = React.useReducer(reducer, { count: 0 });

  return (
    <>
      <p>{state.count}</p>
      <button onClick={() => dispatch({ type: "increment" })}>+1</button>
    </>
  );
}

useReducer 适合什么场景

  1. 多个子状态相关联
  2. 状态流转复杂
  3. 希望更新逻辑集中管理
  4. 想和 Context 组合做轻量状态管理

7.9 自定义 Hook

自定义 Hook 本质上是复用状态逻辑,而不是复用 UI。

function useToggle(initial = false) {
  const [value, setValue] = React.useState(initial);
  const toggle = () => setValue((v) => !v);
  return [value, toggle];
}

7.10 Hooks 总结口诀

useState 管状态,useEffect 管副作用,useRef 管持久引用,useMemo/useCallback 管缓存,useContext 管跨层通信,useReducer 管复杂状态。


8. 组件通信

8.1 父传子

props

8.2 子传父

父组件传回调,子组件调用回调把数据传回去。

8.3 兄弟组件通信

通过共同父组件中转。

8.4 跨层级通信

优先考虑:

  1. Context
  2. 状态提升
  3. 业务状态库

8.5 常见通信方式总结

场景 推荐方式
父到子 props
子到父 回调函数
兄弟组件 状态提升
跨层级共享 Context
全局复杂状态 Zustand / Redux Toolkit 等

8.6 记忆口诀

近的用 props,往上用回调,跨层用 Context,全局用状态库。


9. 状态管理选型

9.1 小项目:useState + Context

适合:

  1. 项目体量小
  2. 全局状态不多
  3. 状态结构简单

优点:

  1. 轻量
  2. 无额外依赖
  3. 容易上手

缺点:

  1. 拆分不好时,容易导致大范围更新
  2. 中大型项目会逐渐混乱

9.2 中项目:Zustand / Jotai

适合:

  1. 希望轻量
  2. API 简洁
  3. 想降低模板代码

优点:

  1. 学习成本低
  2. 写法自然
  3. 通常比传统 Redux 更轻

9.3 大项目:Redux Toolkit

适合:

  1. 复杂状态流
  2. 多人协作
  3. 中大型业务系统
  4. 需要强约束、可追踪更新

优点:

  1. 结构清晰
  2. 生态成熟
  3. 更适合大型团队协作

9.4 选型建议

  1. 小项目不要过度设计
  2. 中项目优先考虑开发效率和可维护性
  3. 大项目更重视规范、可追踪性和协作成本

9.5 一句话记忆

小项目先别上重武器,中项目追求轻量顺手,大项目追求规范和协作。


10. React 18 高频知识点

面试里 React 18 仍然是高频重点,尤其是自动批处理、并发渲染、Suspense、过渡更新。

10.1 自动批处理

React 18 中,更多场景下的更新会自动批处理。

可以先这样理解:

  1. 多次状态更新不一定触发多次渲染
  2. React 会尽量合并同一批次里的更新
  3. 这样能减少不必要渲染

10.2 并发渲染

并发渲染不是“多个线程一起渲染”,而是:

React 可以让渲染工作变得可中断、可恢复、可按优先级调度

这为更流畅的交互提供基础。

10.3 Suspense 增强

Suspense 可以帮助处理异步加载状态,例如组件懒加载。

const UserPage = React.lazy(() => import("./UserPage"));

function App() {
  return (
    <React.Suspense fallback={<div>加载中...</div>}>
      <UserPage />
    </React.Suspense>
  );
}

10.4 过渡更新

React 18 提供了过渡更新相关能力,比如 startTransitionuseTransition

作用:

把“不那么紧急”的更新标记为低优先级,让用户输入等高优先级交互更流畅。

const [isPending, startTransition] = useTransition();

function handleChange(value) {
  setInput(value);
  startTransition(() => {
    setKeyword(value);
  });
}

10.5 useDeferredValue

用于延迟某个值的更新,让界面更顺滑。

适合:

  1. 搜索联想
  2. 大列表过滤
  3. 输入与重计算解耦

10.6 React 18 高频问法

  1. React 18 自动批处理是什么
  2. 并发渲染是什么,不是什么
  3. startTransition 解决什么问题
  4. Suspense 有什么价值

10.7 记忆口诀

自动批处理减少重渲染,并发渲染让更新可打断,Suspense 管等待态,Transition 管优先级。


11. 性能优化手段

11.1 先记住性能优化的原则

React 性能优化不是到处加 Hook,而是先定位问题。

优化顺序建议:

  1. 先确认是否真的有性能问题
  2. 再看是否是不必要渲染
  3. 再看是否计算过重
  4. 最后再上缓存或拆分手段

11.2 React.memo

React.memo 用于缓存组件,在 props 没变时跳过不必要渲染。

const Child = React.memo(function Child({ name }) {
  console.log("Child render");
  return <div>{name}</div>;
});

适合:

  1. 组件纯渲染
  2. props 稳定
  3. 渲染成本相对高

11.3 useMemo / useCallback

这两个不要滥用。

什么时候值得用:

  1. 缓存开销明显小于重复计算成本
  2. 能实际减少子组件无意义渲染
  3. 依赖稳定且收益明确

11.4 状态下沉与状态提升

很多重渲染问题,不是 Hook 不够,而是状态放错位置。

原则:

  1. 谁需要,谁持有
  2. 尽量让高频变化状态靠近使用它的组件
  3. 不要把局部状态无脑提升到最顶层

11.5 代码分割

通过 React.lazy + Suspense 或路由级拆分减少首屏体积。

11.6 虚拟列表

大列表渲染时,只渲染可视区域,避免一次性挂载过多 DOM。

适合:

  1. 商品列表
  2. 聊天记录
  3. 后台表格

11.7 key 的合理使用

稳定 key 能减少错误复用,也能减少不必要的节点变动。

11.8 避免在 render 中创建重计算

例如:

  1. 大数组排序
  2. 复杂过滤
  3. 深度对象转换

可以考虑:

  1. 预处理
  2. useMemo
  3. 后端分页
  4. 虚拟滚动

11.9 性能优化答题模板

面试里可以这样答:

  1. 合理拆分组件,控制渲染范围
  2. 使用 React.memouseMemouseCallback 减少不必要渲染
  3. 对大列表使用虚拟列表
  4. 使用代码分割优化首屏
  5. 结合 React 18 的过渡更新改善交互流畅度

12. 高频面试题

12.1 React 和 Vue 的核心差异怎么答

可简答为:

  1. React 更偏函数式和 UI 组合
  2. React 核心是状态驱动 + JSX
  3. React 更强调“你自己组织应用”,生态选择更自由

12.2 React 中为什么不直接修改 state

答:

  1. React 更依赖不可变更新来识别变化
  2. 直接修改可能导致视图不更新
  3. 也会让状态流变得难以追踪

12.3 useEffect 和 useLayoutEffect 区别

  1. useEffect 在浏览器绘制后执行
  2. useLayoutEffect 在 DOM 更新后、绘制前同步执行

适合:

  1. useEffect 处理大多数副作用
  2. useLayoutEffect 处理布局测量、同步 DOM 调整

12.4 React.memo、useMemo、useCallback 区别

  1. React.memo 缓存组件
  2. useMemo 缓存值
  3. useCallback 缓存函数

12.5 useState 和 useReducer 怎么选

  1. 简单状态用 useState
  2. 状态变化逻辑复杂时用 useReducer
  3. 多个状态相互关联时,useReducer 更清晰

12.6 为什么 key 不能随便用 index

答:

当列表项顺序变化时,React 会错误复用节点,导致输入错位、状态错乱和多余更新。

12.7 Context 会导致什么问题

如果 Context 的 value 频繁变化且作用范围很大,会让大量消费组件重新渲染。

12.8 React 18 新特性有哪些

高频答法:

  1. 自动批处理
  2. 并发渲染能力增强
  3. Suspense 能力增强
  4. 过渡更新

12.9 面试时推荐回答结构

  1. 先说定义
  2. 再说原理
  3. 再说场景
  4. 最后说注意点

例如回答 useMemo

  1. 它用于缓存计算结果
  2. 本质是在依赖不变时复用上一次结果
  3. 适合昂贵计算
  4. 但不应滥用,因为本身也有维护成本

13. 6 小时学习规划

第 1 小时:React 核心心法

目标:

  1. 搞懂声明式 UI
  2. 搞懂组件化
  3. 搞懂 UI = f(state)

必须掌握:

  1. 组件是什么
  2. props 和 state 区别
  3. 单向数据流

第 2 小时:JSX、事件、列表、表单

目标:

  1. 熟悉 JSX 规则
  2. 掌握条件渲染和列表渲染
  3. 搞懂受控和非受控组件

必须掌握:

  1. map + key
  2. onChange + value
  3. 子传父回调

第 3-4 小时:Hooks 核心

目标:

  1. 吃透 useState
  2. 吃透 useEffect
  3. 理解 useRefuseMemouseCallback
  4. 理解 useContextuseReducer

必须掌握:

  1. 为什么 Hook 不能条件调用
  2. 为什么 effect 需要清理
  3. useMemouseCallback 区别

第 5 小时:React 18 + 性能优化

目标:

  1. 掌握自动批处理
  2. 理解并发渲染与过渡更新
  3. 掌握 React 常见优化点

必须掌握:

  1. React.memo
  2. 代码分割
  3. 虚拟列表
  4. 状态下沉

第 6 小时:复盘 + 面试表达

建议:

  1. 默写一个完整的表单组件
  2. 默写一个 useReducer 示例
  3. 讲清楚 React 18 的 4 个关键词
  4. 讲清楚 useEffectuseMemouseCallback

14. 一页速记总结

14.1 React 主线

  1. 组件化
  2. 数据驱动视图
  3. 单向数据流

14.2 基础 API

  1. props:组件输入
  2. state:组件内部状态
  3. children:组件插槽内容

14.3 Hooks

  1. useState:状态
  2. useEffect:副作用
  3. useRef:持久引用
  4. useMemo:缓存值
  5. useCallback:缓存函数
  6. useContext:跨层传值
  7. useReducer:复杂状态

14.4 React 18

  1. 自动批处理
  2. 并发渲染
  3. Suspense 增强
  4. 过渡更新

14.5 优化

  1. 组件拆分
  2. React.memo
  3. useMemo/useCallback
  4. 代码分割
  5. 虚拟列表
  6. 状态下沉

15. 背诵口诀

15.1 React 基础口诀

UI 跟着状态走,组件负责组合,props 往下传,回调用来往上走。

15.2 Hooks 口诀

状态用 state,副作用用 effect,持久引用用 ref,缓存值和函数用 memo、callback。

15.3 React 18 口诀

批处理减少渲染,并发更新可打断,Suspense 管等待,Transition 分轻重。

15.4 性能优化口诀

先找问题,再做缓存;先拆组件,再谈优化。


16. 最后给你的建议

想真正快速学会 React,建议按下面节奏练:

  1. 先手敲 3 个小组件:计数器、表单、列表
  2. 再手敲 3 个 Hook 场景:请求、定时器、缓存
  3. 再手敲 1 个 Context + reducer 的小案例
  4. 最后整理 React 18 和优化题答题模板

真正学会的标准不是“看懂”,而是:

  1. 你能自己写组件
  2. 你能自己拆状态
  3. 你能解释每个 Hook 解决什么问题
  4. 你能说出优化应该从哪下手

把这些打通后,你的 React 使用层能力就很稳了。