# React Hooks 的优势和使用场景
## 1. 代码复用性提升
传统类组件中复用逻辑需使用高阶组件或render props,导致组件树嵌套过深。Hooks通过自定义Hook实现逻辑复用:
```javascript
// 自定义Hook
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
// 多组件复用
function ComponentA() {
const width = useWindowWidth();
// ...
}
function ComponentB() {
const width = useWindowWidth();
// ...
}
2. 逻辑关注点分离
类组件生命周期方法常包含不相关逻辑,Hooks允许按功能组织代码:
function UserProfile({ userId }) {
// 用户数据逻辑
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(data => setUser(data));
}, [userId]);
// 在线状态逻辑
const [isOnline, setIsOnline] = useState(false);
useEffect(() => {
subscribeToOnlineStatus(userId, status => setIsOnline(status));
return () => unsubscribeFromOnlineStatus(userId);
}, [userId]);
}
3. 简化组件代码
对比类组件减少约30%代码量:
// 类组件
class Counter extends React.Component {
state = { count: 0 };
componentDidMount() {
document.title = `Count: ${this.state.count}`;
}
componentDidUpdate() {
document.title = `Count: ${this.state.count}`;
}
render() {
return (
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Count: {this.state.count}
</button>
);
}
}
// Hook组件
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
4. 性能优化更精细
useMemo/useCallback实现细粒度优化:
function ProductList({ products, filter }) {
const filteredProducts = useMemo(() => {
return products.filter(p => p.includes(filter));
}, [products, filter]);
const handleSelect = useCallback((productId) => {
console.log('Selected:', productId);
}, []);
return <List items={filteredProducts} onSelect={handleSelect} />;
}
5. 渐进式采用策略
现有项目可逐步引入Hooks:
- 新组件直接使用Hooks开发
- 旧组件重构时逐步替换生命周期方法
- 禁止在循环/条件语句中使用Hook的规则由ESLint插件保障
6. 常见使用场景
| 场景 | 推荐Hook组合 | 示例 |
|---|---|---|
| 数据获取 | useState + useEffect | 用户数据加载 |
| 事件监听 | useEffect + useRef | 窗口resize事件 |
| 动画控制 | useRef + useEffect | requestAnimationFrame动画循环 |
| 表单处理 | useState + useCallback | 复杂表单验证 |
| 全局状态管理 | useContext + useReducer | 主题切换功能 |
7. 使用注意事项
- 依赖项数组:确保useEffect依赖项完整
// 错误示例(缺少dep依赖)
useEffect(() => {
fetchData(dep);
}, []);
// 正确写法
useEffect(() => {
fetchData(dep);
}, [dep]);
- 自定义Hook规范:
- 命名必须使用
use前缀 - 内部可调用其他Hook
- 遵循Hook调用规则
- 性能陷阱:
// 不必要的重新渲染
const Child = React.memo(function({ onClick }) {
// ...
});
function Parent() {
const [count, setCount] = useState(0);
// 错误:每次渲染创建新函数
const handleClick = () => console.log('Click');
// 正确:使用useCallback
const handleClick = useCallback(() => {
console