# React Hooks
# 为什么用 Hooks
- 在函数组件中使用 state 与生命周期,避免类组件的 this 与繁琐生命周期。
- 逻辑复用通过自定义 Hook 抽取,替代 HOC 与 render props。
- 更细粒度的状态与 effect,便于理解和测试。
# useState
const [state, setState] = useState(initialState)
setState(newState)
setState(prev => prev + 1)
1
2
3
2
3
- initialState 可以是值或函数(惰性初始化,仅首次执行)。
- 更新函数形式用于依赖前一次 state;多次 setState 在事件处理中可能被合并。
- 对象/数组更新需不可变,用展开或新引用。
# useEffect
useEffect(() => {
// 副作用
return () => { /* 清理 */ }
}, [dep1, dep2])
1
2
3
4
2
3
4
- 默认每次渲染后执行;依赖数组为空 [] 仅挂载后执行一次;不传依赖则每次执行。
- 清理函数在下次 effect 前或组件卸载时执行;常用于订阅、定时器、手动 DOM 监听。
- 依赖要写全,否则易出现闭包陈旧值或多余执行;lint 规则会提示。
# useContext
const ThemeContext = createContext(defaultValue)
const value = useContext(ThemeContext)
1
2
2
- 消费最近一层 Provider 的 value;无 Provider 时用 defaultValue。
- value 变化会导致所有消费者重渲染;可拆 Provider 或配合 memo/useMemo 优化。
# useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init)
1
- 适合 state 结构复杂或更新逻辑多的情况;dispatch 稳定,便于向下传递。
- init 为可选初始化函数:state = init(initialArg)。
# useCallback
const fn = useCallback(() => { doSomething(a, b) }, [a, b])
1
- 返回记忆化回调;依赖不变则引用不变,用于避免子组件因回调引用变化而重渲染。
- 依赖要完整;过度使用反而增加记忆成本。
# useMemo
const value = useMemo(() => compute(a, b), [a, b])
1
- 记忆化计算结果;依赖不变则返回上次结果。
- 用于昂贵计算或稳定引用(如传给子组件的对象/数组);不要所有计算都包一层。
# useRef
const ref = useRef(initialValue)
ref.current
1
2
2
- 可变引用,变更 current 不触发重渲染。
- 用途:DOM 引用、保存上一次值、保存定时器/订阅 ID 等。
- forwardRef 可转发 ref 到子组件。
# useImperativeHandle
useImperativeHandle(ref, () => ({
focus: () => { inputRef.current.focus() }
}), [])
1
2
3
2
3
- 与 forwardRef 配合,自定义暴露给父组件的实例方法,而不是直接暴露 DOM。
# useLayoutEffect
- 与 useEffect 签名相同,但同步在 DOM 变更后、浏览器绘制前执行。
- 用于需要同步读取布局或避免闪烁的 DOM 操作;避免在内部做耗时逻辑阻塞绘制。
# 自定义 Hook
- 以 use 开头的函数,内部可调用其它 Hook;用于抽取有状态逻辑。
- 每次调用拥有独立 state;可接收参数、返回状态与操作方法。
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth)
useEffect(() => {
const handler = () => setWidth(window.innerWidth)
window.addEventListener('resize', handler)
return () => window.removeEventListener('resize', handler)
}, [])
return width
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 规则与注意
- 只在顶层调用 Hook,不在条件、循环或嵌套函数中调用。
- 只在 React 函数组件或自定义 Hook 中调用。
- 自定义 Hook 间可组合;依赖数组要如实填写,便于正确执行与清理。