← [ BACK_TO_NOTES ]

React Hooks

React Hooks 的整体分工、使用边界与常见模式总览。

#frame #react #synthesis #growing

[!info] related notes

React Hooks

Hooks 让函数组件拥有状态、上下文、副作用、引用和值缓存等能力。它们不是一组零散 API,而是 React 组件能力的统一入口。

Hooks 也是 React 对组件逻辑组织方式的一次升级:它让函数组件拥有“状态、生命周期、副作用、上下文、性能缓存、可复用逻辑”这些能力。

为什么 Hooks 重要

  • 让函数组件取代大多数类组件场景
  • 让状态逻辑和副作用逻辑可以抽成自定义 Hook 复用
  • 让组件更容易按功能组织,而不是按生命周期切碎

Hooks 到底解决了什么

在 Hooks 之前:

  • 同一件事常被拆到 componentDidMount、componentDidUpdate、componentWillUnmount
  • 复用逻辑经常要靠 HOC 或 render props
  • 函数组件更轻,但能力不完整

Hooks 把“状态 + 副作用 + 逻辑组合”带回了函数组件,让你可以按功能聚合逻辑,而不是被生命周期 API 牵着走。

Hooks 的底层心智模型

组件每次渲染时,函数都会重新执行。React 之所以还能知道“哪个 state 属于哪个 Hook”,依赖的不是变量名,而是 Hook 的调用顺序。

可以把它先粗略理解成:

  • 第 1 个 Hook 槽位
  • 第 2 个 Hook 槽位
  • 第 3 个 Hook 槽位

所以这段代码里:

function Counter() {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('A')
}

React 真正依赖的是:

  • 第 1 个 useState 对应 count
  • 第 2 个 useState 对应 name

可以把 Hooks 分成四组理解

状态类

  • useState
  • useReducer

它们负责让组件记住会影响渲染的值。

进一步看:useState, react-use-reducer

副作用类

  • useEffect
  • useLayoutEffect

它们负责和 React 外部系统同步,而不是单纯“渲染后顺手做点事”。

进一步看:useEffect, react-use-layout-effect

引用与上下文类

  • useRef
  • useContext

它们分别解决“不参与渲染的可变值”和“跨层共享值”的问题。

进一步看:useRef, useContext

性能与体验类

  • useMemo
  • useCallback
  • useTransition
  • useDeferredValue

它们主要用于优化重计算、引用稳定性和交互优先级。

进一步看:useMemo, useCallback

最重要的两条规则

  1. 只在 React 函数组件或自定义 Hook 中调用 Hook
  2. 只在顶层调用,不要放进条件、循环或嵌套函数里

原因不是风格偏好,而是 React 依赖 Hook 的调用顺序来匹配状态槽位。

错误例子:

function Bad({ visible }: { visible: boolean }) {
  if (visible) {
    useEffect(() => {
      console.log('shown')
    }, [])
  }

  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

当 visible 一会儿是 true,一会儿是 false 时,Hook 顺序就乱了。

为什么名字都要以 use 开头

这不只是命名风格。

  • 它告诉团队和读代码的人:这是 Hook,不是普通工具函数
  • 它让 ESLint 和工具链知道:这里要遵守 Hook 规则
  • 它意味着这个函数内部可能继续调用其他 Hook

自定义 Hook 的价值

自定义 Hook 复用的是“状态 + 副作用 + 处理逻辑”,而不是直接复用 UI 结构。

常见例子有:useFetch、useToggle、useDebounce、usePrevious。

进一步看:react-custom-hooks

Hooks 学习里真正难的点

真正难的不是记住 API 名字,而是搞懂:

  • 为什么 Hook 只能顶层调用
  • 为什么每次渲染都会形成新闭包
  • 为什么 useEffect 不是“渲染后随便写逻辑”
  • 为什么依赖数组必须真实反映依赖
  • 为什么 useMemo / useCallback 不是默认必加

一套选择 Hook 的思维框架

  1. 需要让 UI 记住某个值:useState / react-use-reducer
  2. 需要和外部系统同步:useEffect / react-use-layout-effect
  3. 只想保存一个不触发渲染的值:useRef
  4. 需要跨层传值:useContext
  5. 有昂贵计算或需要稳定对象引用:useMemo
  6. 需要稳定函数引用:useCallback
  7. 想复用一段“状态 + 副作用 + 行为”:react-custom-hooks

最容易误用的 Hook

最容易被滥用的是 useEffect。很多本该写在渲染逻辑或事件处理里的代码,被误塞进了副作用里。要单独理解时,优先看 useEffect。

最短记忆方式

  • Hooks 不是“函数组件的补丁”
  • Hooks 是函数组件获取 React 能力的统一接口
  • 真正会用 Hooks 的标志,是能区分状态、引用、副作用和性能优化各自的边界

学习检查

不看正文回答:

  1. Hooks 解决的核心问题为什么不只是“让函数组件有 state”?
  2. React 为什么要求 Hook 调用顺序稳定?
  3. state、effect、ref、context、memoization 分别解决哪一类问题?
  4. 为什么自定义 Hook 复用的是状态与行为逻辑,而不是 UI 结构?
  5. 为什么 useEffect 是最容易被滥用的 Hook?
  6. 一个值只需要跨 render 保留但不驱动 UI 时,为什么更接近 ref 而不是 state?
  7. 一个昂贵计算是否应该立刻加 useMemo?你还需要哪些证据?
  8. 给一个新组件需求,能否先按职责选 Hook,再写 API?
创建于 2025/1/1 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本