React Hooks 的优势和使用场景

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

## 核心优势

### 1. 逻辑复用更简单
- 替代高阶组件和render props模式
- 自定义Hook可提取组件逻辑
- 示例:使用`useFetch`复用数据请求逻辑
```javascript
function useFetch(url) {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(setData);
  }, [url]);

  return data;
}

2. 代码组织更清晰

  • 相关逻辑集中管理(对比class组件的生命周期分散)
  • 副作用代码集中到useEffect
  • 状态管理集中到useState/useReducer

3. 函数式组件能力增强

  • 支持状态管理(useState)
  • 支持生命周期(useEffect)
  • 支持ref(useRef)
  • 支持context(useContext)

4. 性能优化更精细

  • useMemo缓存计算结果
  • useCallback缓存函数
  • 对比class组件shouldComponentUpdate更灵活

主要使用场景

1. 状态管理

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Clicked {count} times
    </button>
  );
}

2. 副作用处理

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []);

  return <div>Seconds: {seconds}</div>;
}

3. 上下文访问

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme }}>Themed</button>;
}

4. 表单处理

function Form() {
  const [value, setValue] = useState('');
  
  const handleSubmit = useCallback((e) => {
    e.preventDefault();
    console.log(value);
  }, [value]);

  return (
    <form onSubmit={handleSubmit}>
      <input 
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
    </form>
  );
}

最佳实践

  1. 遵循Hook调用规则

    • 只在顶层调用Hook
    • 只在React函数中调用Hook
  2. 合理拆分自定义Hook

    • 按功能维度拆分
    • 保持Hook单一职责
  3. 性能优化要点

    • 正确设置依赖数组
    • 避免在渲染中创建新对象/函数
  4. 测试策略

    • 使用@testing-library/react-hooks
    • 单独测试自定义Hook

常见问题解决方案

1. 无限循环问题

// 错误示例
useEffect(() => {
  setCount(count + 1); // 会导致无限渲染
}, [count]);

// 正确写法
useEffect(() => {
  setCount(c => c + 1); // 使用函数式更新
}, []);

2. 过时闭包问题

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      console.log(count); // 总是打印初始值
    }, 1000);
    return () => clearInterval(id);
  }, []); // 缺少count依赖

  // 正确做法:要么添加依赖,要么使用ref
}

3. 条件执行问题

// 错误示例
if (condition) {
  useEffect(() => {...}); // 违反Hook规则
}

// 正确做法:在Hook内部判断
useEffect(() => {
  if (condition) {
    // 执行逻辑
  }
}, [condition]);

总结

React Hooks通过函数式编程范式,解决了class组件的多个痛点:

  1. 逻辑复用困难
  2. 生命周期带来的代码分散
  3. 组件嵌套过深
  4. 学习成本高

合理使用Hooks可以显著提升代码的可维护性和可测试性,是现代React开发的推荐实践。