“Hook 不是魔法,它只是让函数组件更强大的方法。”
一、React Hook 是什么?
React Hook 是 React 16.8 引入的新特性,它的出现解决了两个痛点:
- 函数组件无法拥有状态(state)与生命周期逻辑
- 逻辑复用困难,HOC(高阶组件)和 render props 会导致组件嵌套过深
Hook 用函数的形式,把状态、副作用、上下文等功能“钩”进函数组件,让你不用写 class 就能享受这些特性。
简单来说:
- 以前:需要 class 才能管理 state 和生命周期
- 现在:函数组件 + Hook 就能搞定
二、Hook 的分类
1. React 内置 Hook
状态管理类
-
useState
让函数组件拥有本地状态const [count, setCount] = useState(0); -
useReducer
复杂状态管理,类似 Redux 的 reducer 模式const [state, dispatch] = useReducer(reducer, initialState);
副作用类
-
useEffect
处理副作用(数据请求、订阅、DOM 操作等)useEffect(() => { document.title = `Count: ${count}`; }, [count]); -
useLayoutEffect
同步触发副作用(DOM 更新前后需要精确测量的场景)
性能优化类
useMemo
缓存计算结果,避免重复运算useCallback
缓存函数引用,避免子组件重复渲染
引用类
-
useRef
保存可变值或直接访问 DOMconst inputRef = useRef();
其他
useContext
订阅 React ContextuseImperativeHandle
自定义暴露给父组件的 ref APIuseId
生成稳定的唯一 ID(React 18)
2. 自定义 Hook
自定义 Hook 是一个命名以 use 开头的普通函数,可以在里面使用其他 Hook,从而实现逻辑复用。
例子:封装窗口大小监听
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const onResize = () => setSize({ width: window.innerWidth, height: window.innerHeight });
window.addEventListener('resize', onResize);
return () => window.removeEventListener('resize', onResize);
}, []);
return size;
}
// 使用
function App() {
const { width, height } = useWindowSize();
return <p>{width} x {height}</p>;
}
三、Hook 的使用规则
React 有两条黄金法则:
-
只在最顶层调用 Hook
- 不要在循环、条件或嵌套函数里调用 Hook
-
只在 React 函数组件或自定义 Hook 中调用 Hook
- 不要在普通函数里直接调用
为什么?
React 通过调用顺序来匹配 Hook 的状态存储位置,如果调用顺序变化,状态就会错位。
四、常见误区与优化建议
-
useEffect依赖列表- 忘记依赖会导致数据不同步
- 依赖过多会导致不必要的重复执行
-
频繁创建函数导致子组件渲染
- 使用
useCallback缓存函数
- 使用
-
滥用
useMemo- 优化是有成本的,不要对轻量计算滥用缓存
-
状态提升过度
- 把状态放在需要的最小范围内
五、Hook 带来的优势
- 更少的样板代码:不再需要写 class 和绑定 this
- 逻辑拆分更自然:状态和副作用可以按功能组织,而不是生命周期方法
- 易于复用:自定义 Hook 让共享逻辑更简单
- 更好地支持函数式编程思路
六、总结
React Hook 改变了我们写 React 组件的方式,让函数组件成为主流。
掌握内置 Hook 的使用场景 + 学会编写自定义 Hook,是写好现代 React 代码的关键。
如果过去更多依赖 class 组件,可以先从把一个简单组件改写成函数组件 + Hook 开始,然后逐步迁移更复杂的逻辑。

1049

被折叠的 条评论
为什么被折叠?



