React Hooks 的优势和使用场景

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

## 核心优势

### 1. 逻辑复用更简单
- 传统方案:高阶组件(HOC)或render props会导致"嵌套地狱"
- Hooks方案:自定义Hook可提取状态逻辑,实现干净复用

```jsx
// 自定义Hook示例
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;
}

// 在组件中使用
function MyComponent() {
  const width = useWindowWidth();
  return <div>窗口宽度: {width}px</div>;
}

2. 代码组织更清晰

  • 传统class组件:相关逻辑分散在不同生命周期
  • Hooks方案:按功能组织代码,相关逻辑集中处理
function UserProfile({ userId }) {
  // 用户数据相关
  const [user, setUser] = useState(null);
  useEffect(() => {
    fetchUser(userId).then(data => setUser(data));
  }, [userId]);

  // 主题偏好相关
  const [theme, setTheme] = useLocalStorage('theme', 'light');
  
  // 渲染逻辑
  if (!user) return <Loader />;
  return (
    <div className={theme}>
      <Avatar user={user} />
      <ProfileDetails user={user} />
    </div>
  );
}

3. 减少组件复杂度

  • 无需处理this绑定问题
  • 函数组件更轻量,性能更好
  • 更易于理解和测试

主要使用场景

1. 状态管理

  • useState: 基础状态管理
  • useReducer: 复杂状态逻辑
function Counter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(c => c + 1);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  );
}

2. 副作用处理

  • useEffect: 数据获取、订阅、手动DOM操作
  • useLayoutEffect: DOM变更后同步执行
function DataFetcher({ url }) {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    let isMounted = true;
    
    fetch(url)
      .then(res => res.json())
      .then(data => isMounted && setData(data))
      .catch(err => isMounted && setError(err));

    return () => { isMounted = false };
  }, [url]);

  if (error) return <ErrorDisplay error={error} />;
  if (!data) return <Loader />;
  return <DataDisplay data={data} />;
}

3. 性能优化

  • useMemo: 缓存计算结果
  • useCallback: 缓存函数引用
function ExpensiveComponent({ items, filter }) {
  const filteredItems = useMemo(() => {
    return items.filter(item => item.includes(filter));
  }, [items, filter]);

  return <List items={filteredItems} />;
}

4. 访问DOM/Ref

  • useRef: 获取DOM引用或保存可变值
function TextInputWithFocus() {
  const inputEl = useRef(null);
  
  const focusInput = () => {
    inputEl.current.focus();
  };

  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={focusInput}>Focus</button>
    </>
  );
}

5. 上下文访问

  • useContext: 无需嵌套消费Context
const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  
  return (
    <button style={{ background: theme === 'dark' ? '#333' : '#fff' }}>
      Themed Button
    </button>
  );
}

最佳实践

  1. 遵循Hook调用规则

    • 只在React函数组件或自定义Hook中调用
    • 不要在循环、条件或嵌套函数中调用
  2. 合理拆分自定义Hook

    • 每个Hook应该只关注一个特定功能
    • 命名