React Hooks 的优势和使用场景

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

## 一、React Hooks 核心优势

1. **逻辑复用更简单**
   - 告别高阶组件和render props的嵌套地狱
   - 自定义Hook可以提取状态逻辑,实现真正的功能复用
   ```jsx
   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;
   }
  1. 代码组织更清晰

    • 相关逻辑可以集中在一起
    • 告别生命周期方法的强制拆分
    // 传统class组件
    componentDidMount() { /* 初始化A */ }
    componentDidUpdate() { /* 更新A */ }
    componentWillUnmount() { /* 清理A */ }
    
    // Hooks方式
    useEffect(() => {
      // 初始化A
      return () => { /* 清理A */ }
    }, [/* A的依赖 */]);
    
  2. 学习成本更低

    • 只需掌握useState/useEffect等少量API
    • 不用再理解this绑定问题

二、常用Hooks使用场景

1. useState - 状态管理

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

2. useEffect - 副作用处理

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => subscription.unsubscribe(); // 清理函数
}, [props.source]); // 依赖数组

3. useContext - 跨组件通信

const themes = { light: { foreground: '#000' } };
const ThemeContext = createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.light}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme.foreground }}>按钮</button>;
}

4. useReducer - 复杂状态逻辑

function reducer(state, action) {
  switch (action.type) {
    case 'increment': return {count: state.count + 1};
    default: throw new Error();
  }
}

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

三、进阶Hooks应用

  1. 性能优化

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);
    
  2. DOM操作

    function TextInputWithFocusButton() {
      const inputEl = useRef(null);
      const onButtonClick = () => inputEl.current.focus();
      return (
        <>
          <input ref={inputEl} type="text" />
          <button onClick={onButtonClick}>Focus</button>
        </>
      );
    }
    
  3. 自定义Hook示例

    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
      useEffect(() => {
        const handleStatusChange = status => setIsOnline(status.isOnline);
        ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
        return () => ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
      }, [friendID]);
      return isOnline;
    }
    

四、最佳实践

  1. Hooks使用规则

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

    • 合理使用依赖数组
    • 复杂计算使用useMemo
    • 避免在渲染函数中直接创建对象/函数
  3. 代码组织建议

    • 相关逻辑组织在同一个useEffect
    • 复杂组件拆分为多个小Hook
    • 提取可复用逻辑到自定义Hook

五、与传统方案的对比

特性Class组件Hooks组件
代码量少30%-50%
逻辑复用困难简单
学习曲线陡峭平缓
性能优化需要手动内置优化
测试友好度一般更好

六、适用场景总结

  1. 推荐使用Hooks的场景

    • 新项目开发
    • 需要逻辑复用的组件
    • 复杂状态管理的组件
    • 需要更好性能优化的组件
  2. 仍需谨慎的场景

    • 现有Class组件的稳定维护
    • 需要getSnapshotBeforeUpdate等特殊生命周期的场景
    • 尚未完全支持Hooks的第三方库集成

Hooks代表了React未来的发展方向,虽然不强制迁移现有代码,但新项目强烈推荐采用Hooks方案。