主题
概念卡片:React Hook
一句话机制:Hook 是 React 16.8 引入的,让函数组件也能拥有 state 和「生命周期副作用」;它以
use开头(useState/useEffect/useMemo…),且必须在函数组件顶层按固定顺序调用——React 靠调用顺序把每次渲染的 Hook 状态对应起来。
为什么需要 Hook(class 组件的问题)
class 组件能定义 state、有生命周期,但逻辑难以拆分(componentDidMount 里混着请求+监听+清理)、this 指向烦人、状态复用要靠高阶组件/render props 层层嵌套。Hook 让函数组件直接拥有这些能力,代码更简洁。
关键代码示例:class vs Hook
jsx
// class 组件(要管理 this)
class Counter extends PureComponent {
state = { counter: 0 }
increment = () => this.setState({ counter: this.state.counter + 1 })
}
// 函数组件 + Hook(简洁,无 this)
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0) // 返回 [值, 设值函数]
return <button onClick={() => setCount(count + 1)}>{count}</button>
}useState 返回值解构:const [count, setCount] = useState(0) 等价于 const counter = useState(0); counter[0] / counter[1]。重渲染时 React 保留 state,不会重置为初始值。
useEffect 处理副作用:
js
useEffect(() => {
// 挂载 + 依赖变化时执行(发请求、加监听)
return () => { /* 清理函数:卸载/下次执行前调用 */ }
}, [依赖数组]) // [] 只执行一次;不传则每次渲染都执行核心 Hook 速查
| Hook | 作用 |
|---|---|
useState(x) | 声明 state,返回 [state, setState] |
useEffect(fn, deps) | 副作用,deps 控制执行时机 |
useMemo(fn, deps) | 缓存计算结果 |
useCallback(fn, deps) | 缓存函数引用 |
useRef(x) | 可变引用(不触发渲染) |
不变量(必须成立的约束)
- Hook 只能在函数组件顶层调用,不能在条件、循环、嵌套函数里调——顺序变了状态就错位。
useState的 setter 不自动合并对象:setObj({...obj, b:2})要手动展开,不像类组件setState会合并。useEffect依赖数组决定何时执行:[]只执行一次,漏依赖会拿到旧值(stale closure)。- Hook 只能在函数组件或自定义 Hook 里用,不能在类组件或普通函数里用。
踩坑案例
- 现象:在
if里条件性调用useState,组件偶发状态错乱。 原因:Hook 靠调用顺序对应状态,条件调用会打乱顺序。解决:把条件判断移到 Hook 内部或放在 Hook 调用之后。
常见误解
- 以为 Hook 的 setter 和类组件
setState一样自动合并对象 → 实际不合并,需手动展开。 useEffect依赖数组漏写依赖 → 闭包捕获旧值,逻辑用错数据。
关联
- 状态对比:概念卡片:React状态管理与setState
- 总览:React技术栈总览
- 源:
B40-资源/语雀-Java开发/前端技术/✅React全家桶/♂️ReactHook基本使用