React Hooks 的优势和使用场景

68 阅读2分钟
# 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 + useEffectrequestAnimationFrame动画循环
表单处理useState + useCallback复杂表单验证
全局状态管理useContext + useReducer主题切换功能

7. 使用注意事项

  1. 依赖项数组:确保useEffect依赖项完整
// 错误示例(缺少dep依赖)
useEffect(() => {
  fetchData(dep);
}, []);

// 正确写法
useEffect(() => {
  fetchData(dep);
}, [dep]);
  1. 自定义Hook规范
  • 命名必须使用use前缀
  • 内部可调用其他Hook
  • 遵循Hook调用规则
  1. 性能陷阱
// 不必要的重新渲染
const Child = React.memo(function({ onClick }) {
  // ...
});

function Parent() {
  const [count, setCount] = useState(0);
  
  // 错误:每次渲染创建新函数
  const handleClick = () => console.log('Click');
  
  // 正确:使用useCallback
  const handleClick = useCallback(() => {
    console