React Hooks 的优势和使用场景

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

## 核心优势

1. **简化组件逻辑**
   - 将相关逻辑聚合到独立 Hook 中,告别生命周期方法的分散
   - 示例:将数据获取和状态管理合并为自定义 Hook
   ```javascript
   function useUserData(userId) {
     const [data, setData] = useState(null);
     useEffect(() => {
       fetchUser(userId).then(setData);
     }, [userId]);
     return data;
   }
  1. 更好的代码复用

    • 突破 HOC 和 render props 的嵌套限制
    • 自定义 Hook 可被多个组件共享
    // 多个组件共用窗口尺寸监听
    function useWindowSize() {
      const [size, setSize] = useState({
        width: window.innerWidth,
        height: window.innerHeight
      });
      
      useEffect(() => {
        const handler = () => setSize({
          width: window.innerWidth,
          height: window.innerHeight
        });
        window.addEventListener('resize', handler);
        return () => window.removeEventListener('resize', handler);
      }, []);
      
      return size;
    }
    
  2. 更直观的状态管理

    • useState 提供更清晰的状态更新方式
    • 避免 this.setState 的合并问题
    // 传统 class 组件
    state = { count: 0 };
    handleClick = () => this.setState({ count: this.state.count + 1 });
    
    // Hook 版本
    const [count, setCount] = useState(0);
    const handleClick = () => setCount(count + 1);
    

主要使用场景

  1. 状态逻辑复用

    • 表单处理、动画控制等可提取为自定义 Hook
    function useFormInput(initialValue) {
      const [value, setValue] = useState(initialValue);
      const handleChange = (e) => setValue(e.target.value);
      return { value, onChange: handleChange };
    }
    
  2. 副作用管理

    • 数据获取、订阅、DOM 操作等副作用
    useEffect(() => {
      const subscription = dataSource.subscribe();
      return () => subscription.unsubscribe();
    }, [dataSource]);
    
  3. 性能优化

    • useMemo 和 useCallback 避免不必要的计算和渲染
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);
    
  4. 跨组件状态共享

    • 配合 Context API 实现轻量级状态管理
    const ThemeContext = createContext('light');
    
    function App() {
      return (
        <ThemeContext.Provider value="dark">
          <Toolbar />
        </ThemeContext.Provider>
      );
    }
    
    function Toolbar() {
      const theme = useContext(ThemeContext);
      return <div>{theme}</div>;
    }
    

最佳实践

  1. Hook 使用规则

    • 只在 React 函数组件顶层调用 Hook
    • 不要在循环、条件或嵌套函数中调用 Hook
  2. 自定义 Hook 规范

    • 命名以 use 开头
    • 内部可以调用其他 Hook
    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
      // ...
      return isOnline;
    }
    
  3. 性能优化技巧

    • 合理设置依赖数组
    • 复杂组件拆分为多个小 Hook
    function useUser(userId) {
      const [user, setUser] = useState(null);
      useEffect(() => {
        fetchUser(userId).then(setUser);
      }, [userId]);
      return user;
    }
    

注意事项

  1. Class 组件对比

    • 生命周期方法对应关系:
      • constructor → useState
      • componentDidMount → useEffect(fn, [])
      • componentDidUpdate → useEffect(fn)
      • componentWillUnmount → useEffect(() => { return fn }, [])
  2. 常见误区

    • 过度使用 useEffect("依赖项地狱")
    • 忽略 cleanup 函数导致内存泄漏
    // 错误示例:缺少 cleanup
    useEffect(() => {
      socket.on('message', handler);
    }, []);
    
    // 正确写法
    useEffect(() => {
      socket.on('message', handler);