React的hooks基础总结
# 一、Hooks 设计初衷(为什么会有 Hooks)
在 React 16.8 之前:
- 逻辑复用 → HOC / render props
- 状态管理 → class component
- 生命周期 → 分散在 componentDidMount / update / unmount
- this 指向复杂
- 逻辑分散难维护
Hooks 的目标:
- ✅ 逻辑复用
- ✅ 函数组件拥有状态
- ✅ 副作用逻辑可组合
- ✅ 更好的 tree shaking
# 二、核心 Hooks 总览
# 1️⃣ useState
const [state, setState] = useState(initialState)
1
# 关键点
- setState 是异步批处理(React 18 自动批处理)
- 更新可能被合并
- 支持函数式更新
setCount(prev => prev + 1)
1
# 面试深挖
为什么不能在条件里写 useState?
- Hooks 调用顺序必须稳定(依赖 fiber 的 hooks 链表)
# 2️⃣ useEffect
副作用处理核心 API。
useEffect(() => {
// effect
return () => {
// cleanup
}
}, [deps])
1
2
3
4
5
6
2
3
4
5
6
# 执行时机
- 首次渲染后执行
- 依赖变化后执行
- 卸载执行 cleanup
# React 18 重要变化
- 严格模式下会执行两次(开发环境)
- 用于检测副作用安全性
# useEffect vs useLayoutEffect
| useEffect | useLayoutEffect | |
|---|---|---|
| 执行时机 | DOM 渲染后 | DOM 渲染前 |
| 是否阻塞渲染 | 不阻塞 | 阻塞 |
| 场景 | 请求/订阅 | DOM 读写 |
# 3️⃣ useRef
const ref = useRef(null)
1
特点:
- 不触发重渲染
- 保存可变值
- 可获取 DOM
高级用法:
const latestFn = useRef(fn)
1
解决闭包陷阱问题。
# 4️⃣ useMemo
const memoValue = useMemo(() => compute(), [deps])
1
- 缓存计算结果
- 防止重复计算
- 用于对象引用稳定
⚠️ 滥用会增加内存压力
# 5️⃣ useCallback
const memoFn = useCallback(() => {}, [deps])
1
本质:
useMemo(() => fn, deps)
1
用途:
- 子组件 React.memo 优化
- 事件函数引用稳定
# 6️⃣ useContext
const value = useContext(Context)
1
问题:
- 任意 value 变化 → 所有 consumer 重新渲染
解决:
- 拆分 context
- useContextSelector
- 外部状态库
# 7️⃣ useReducer
const [state, dispatch] = useReducer(reducer, initialState)
1
适合:
- 复杂状态
- 多字段联动
- 表单管理
类比:
- Redux 精简版
# 三、React 18 新 Hooks
# useTransition
解决卡顿问题。
const [isPending, startTransition] = useTransition()
1
- 标记低优先级更新
- 不阻塞 UI
适合:
- 搜索过滤
- 大列表渲染
# useDeferredValue
const deferred = useDeferredValue(value)
1
延迟更新某个值。
# useId
解决 SSR hydration id 不一致问题。
# 四、Hooks 底层原理
在 React 内部:
- 每个 Fiber 有一个 hooks 单向链表
- 每个 hook 结构:
{
memoizedState,
queue,
next
}
1
2
3
4
5
2
3
4
5
调用顺序决定定位:
useState()
useEffect()
useState()
1
2
3
2
3
必须顺序一致。
这就是为什么:
❌ 不能在 if 里调用 hooks
# 五、闭包陷阱问题(高频)
useEffect(() => {
setInterval(() => {
console.log(count)
}, 1000)
}, [])
1
2
3
4
5
2
3
4
5
count 永远是初始值。
解决方案:
- 依赖数组加 count
- useRef 保存最新值
- 使用函数式更新
# 六、自定义 Hooks
# 本质
函数 + 内部调用其他 hooks
例:
function useRequest(url) {
const [data, setData] = useState(null)
useEffect(() => {
fetch(url).then(r => r.json()).then(setData)
}, [url])
return data
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
优势:
- 逻辑复用
- 关注点分离
- 组合式编程
# 七、性能优化思路
# 1️⃣ 减少无意义重渲染
- React.memo
- useMemo
- useCallback
- 拆分组件
# 2️⃣ 状态粒度控制
- 局部状态
- 避免顶层大对象
# 3️⃣ 长列表
- 虚拟列表
- useTransition
- 分块渲染
# 八、和 Vue3 Composition API 对比
| React Hooks | Vue3 |
|---|---|
| useState | ref/reactive |
| useEffect | watchEffect |
| 自定义 hook | composable |
| useMemo | computed |
| fiber 调度 | 响应式依赖追踪 |
最大区别:
- React 依赖调用顺序
- Vue 依赖 Proxy 依赖收集
# 十、最终总结
Hooks 是 React 在函数式组件中实现状态和副作用管理的机制,本质是基于 Fiber 链表按调用顺序存储状态,通过闭包和调度系统实现响应式更新。
上次更新: 2026/03/04, 09:44:50