React Hooks 的优势和使用场景

39 阅读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组件的生命周期分散)
    • 减少不必要的嵌套层级
  2. 学习成本更低

    • 无需理解this绑定
    • 无需区分类组件和函数组件
  3. 性能优化更精细

    • 可针对特定state进行优化
    • 避免不必要的生命周期执行

主要Hooks使用场景

useState

  • 管理组件内部状态
  • 适合简单状态管理
const [count, setCount] = useState(0);

useEffect

  • 副作用处理(数据获取、订阅、手动DOM操作)
  • 替代componentDidMount、componentDidUpdate和componentWillUnmount
useEffect(() => {
  // 组件挂载时执行
  const subscription = props.source.subscribe();
  
  return () => {
    // 组件卸载时执行清理
    subscription.unsubscribe();
  };
}, [props.source]); // 仅在props.source变化时重新执行

useContext

  • 跨组件共享状态
  • 替代部分Redux场景
const theme = useContext(ThemeContext);

useReducer

  • 复杂状态逻辑管理
  • 适合状态更新逻辑复杂的场景
const [state, dispatch] = useReducer(reducer, initialState);

useCallback

  • 缓存回调函数
  • 避免子组件不必要的重渲染
const memoizedCallback = useCallback(
  () => { doSomething(a, b); },
  [a, b],
);

useMemo

  • 缓存计算结果
  • 性能优化手段
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useRef

  • 访问DOM节点
  • 保存可变值(不触发重渲染)
const inputEl = useRef(null);
const onButtonClick = () => inputEl.current.focus();

最佳实践

  1. Hook调用规则

    • 只在React函数组件或自定义Hook中调用
    • 不要在循环、条件或嵌套函数中调用
  2. 性能优化

    • 合理使用依赖数组
    • 避免在useEffect中执行不必要的操作
  3. 自定义Hook规范

    • 命名以use开头
    • 可组合使用内置Hook
  4. 代码组织建议

    • 相关逻辑组织在一起
    • 复杂组件可拆分为多个自定义Hook

适用场景

  1. 新项目开发

    • 优先使用函数组件+Hook模式
  2. 旧项目改造

    • 逐步替换class组件
    • 优先改造复杂生命周期组件
  3. 状态管理

    • 简单场景:useState/useReducer
    • 复杂场景:结合Context API或状态管理库
  4. 副作用处理

    • 数据获取、事件监听等场景使用useEffect

注意事项

  1. 不要滥用useEffect

    • 避免在单个组件中使用过多useEffect
    • 考虑将相关逻辑提取到自定义Hook
  2. 依赖数组要完整

    • 确保包含所有外部依赖
    • 使用eslint-plugin-react-hooks插件检查
  3. 避免过度优化

    • 只在必要时使用useCallback/useMemo
    • 通过性能测试验证优化效果
  4. class组件仍有价值

    • 错误边界等特殊场景仍需class组件
    • 不必强制转换所有现有组件