React Hooks 的优势和使用场景

50 阅读2分钟
# React Hooks 的优势和使用场景

## 核心优势

1. **逻辑复用更简单**
   - 替代高阶组件和render props模式
   - 自定义Hook可以提取组件逻辑,实现跨组件复用
   ```jsx
   // 自定义Hook示例
   function useWindowSize() {
     const [size, setSize] = useState({
       width: window.innerWidth,
       height: window.innerHeight
     });
   
     useEffect(() => {
       const handleResize = () => setSize({
         width: window.innerWidth,
         height: window.innerHeight
       });
       window.addEventListener('resize', handleResize);
       return () => window.removeEventListener('resize', handleResize);
     }, []);
   
     return size;
   }
  1. 代码组织更清晰

    • 相关逻辑可以集中在一起
    • 避免生命周期方法中分散的逻辑
    // 传统class组件 vs Hooks组件
    // Before: 分散在不同生命周期
    componentDidMount() { /* 逻辑A + 逻辑B */ }
    componentDidUpdate() { /* 逻辑A + 逻辑B */ }
    
    // After: 相关逻辑集中
    useEffect(() => { /* 逻辑A */ }, [deps]);
    useEffect(() => { /* 逻辑B */ }, [deps]);
    
  2. 减少组件嵌套

    • 消除高阶组件带来的组件层级
    • 降低组件树复杂度
  3. 学习成本更低

    • 无需理解class的this绑定问题
    • 统一函数组件开发方式

主要使用场景

1. 状态管理

useState 适用于:

  • 组件内部简单状态
  • 不需要复杂状态逻辑的场景
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Clicked {count} times
    </button>
  );
}

2. 副作用处理

useEffect 适用于:

  • 数据获取
  • 事件监听
  • DOM操作
useEffect(() => {
  const subscription = props.source.subscribe();
  return () => subscription.unsubscribe(); // 清理函数
}, [props.source]); // 依赖项

3. 性能优化

useMemo/useCallback 适用于:

  • 计算昂贵的值
  • 避免不必要的重新渲染
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);

4. 复杂状态逻辑

useReducer 适用于:

  • 具有复杂状态逻辑的组件
  • 需要多个子值的状态对象
function reducer(state, action) {
  switch (action.type) {
    case 'increment': return {count: state.count + 1};
    case 'decrement': return {count: state.count - 1};
    default: throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, {count: 0});
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}

5. 访问DOM元素

useRef 适用于:

  • 访问DOM节点
  • 存储可变值而不触发重新渲染
function TextInput() {
  const inputEl = useRef(null);
  
  const focusInput = () => inputEl.current.focus();
  
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={focusInput}>Focus</button>
    </>
  );
}

最佳实践

  1. 遵循Hooks规则

    • 只在顶层调用Hooks
    • 只在React函数中调用Hooks
  2. 合理拆分Hooks

    • 每个Hook负责单一功能
    • 复杂逻辑拆分为多个Hooks
  3. 优化依赖数组

    • 确保包含所有依赖项
    • 避免不必要的依赖
  4. 自定义Hook命名

    • 使用use前缀
    • 语义化命名
  5. 性能优化

    • 合理使用useMemo/useCallback
    • 避免在渲染中创建新对象