React Hooks 的优势和使用场景

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

## 核心优势

### 1. 逻辑复用更简单
- 传统方案:高阶组件(HOC)和render props会导致"嵌套地狱"
- Hooks方案:自定义Hook可提取状态逻辑,实现干净复用
```javascript
// 自定义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;
}
// 任何组件都可直接使用
function MyComponent() {
  const { width } = useWindowSize();
  return <div>Window width: {width}px</div>;
}

2. 代码组织更清晰

  • 传统class组件:相关逻辑分散在不同生命周期
  • Hooks方案:按功能组织代码,相关逻辑集中管理
function FriendStatus(props) {
  // 状态管理集中
  const [isOnline, setIsOnline] = useState(null);
  
  // 副作用集中
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribe(props.friend.id, handleStatusChange);
    return () => ChatAPI.unsubscribe(props.friend.id, handleStatusChange);
  }, [props.friend.id]);

  // UI渲染
  if (isOnline === null) return 'Loading...';
  return isOnline ? 'Online' : 'Offline';
}

3. 学习成本更低

  • 无需理解class的this绑定问题
  • 减少生命周期方法的学习负担
  • 更接近纯函数编程思想

主要使用场景

1. 状态管理

  • useState: 基础状态管理
  • useReducer: 复杂状态逻辑
function counterReducer(state, action) {
  switch (action.type) {
    case 'increment': return {count: state.count + 1};
    case 'decrement': return {count: state.count - 1};
    default: throw new Error();
  }
}

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

2. 副作用处理

  • useEffect: 数据获取、订阅、手动DOM操作
  • useLayoutEffect: DOM变更后同步执行
function DataFetcher({ id }) {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    let ignore = false;
    async function fetchData() {
      const response = await fetch(`/api/data/${id}`);
      const result = await response.json();
      if (!ignore) setData(result);
    }
    
    fetchData();
    return () => { ignore = true; };
  }, [id]); // id变化时重新执行

  return data ? <div>{data.name}</div> : <div>Loading...</div>;
}

3. 性能优化

  • useMemo: 缓存计算结果
  • useCallback: 缓存函数引用
function Parent({ a, b }) {
  // 只有a变化时才会重新计算
  const memoizedValue = useMemo(() => computeExpensiveValue(a), [a]);
  
  // 只有b变化时才会重新创建函数
  const memoizedCallback = useCallback(() => doSomething(b), [b]);

  return <Child onClick={memoizedCallback} value={memoizedValue} />;
}

4. 访问DOM和ref

  • useRef: 访问DOM节点/保存可变值
function TextInput() {
  const inputRef = useRef(null);
  
  const focusInput = () => {
    inputRef.current.focus();
  };

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

5. 上下文访问

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

function Themed