React Hooks 的优势和使用场景

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

## 1. React Hooks 的核心优势

### 1.1 简化组件逻辑
Hooks 允许在不编写 class 的情况下使用 state 和其他 React 特性。通过将相关逻辑组织到独立的 Hook 中,可以更清晰地分离关注点。

```javascript
// 传统 class 组件
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  
  render() {
    return <button onClick={() => this.setState({ count: this.state.count + 1 })}>
      Clicked {this.state.count} times
    </button>;
  }
}

// 使用 Hooks 的函数组件
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>
    Clicked {count} times
  </button>;
}

1.2 复用状态逻辑

自定义 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>Window width: {width}</div>;
}

1.3 更细粒度的性能优化

Hooks 如 useMemouseCallback 可以精确控制组件的重渲染,避免不必要的计算和 DOM 操作。

function ExpensiveComponent({ list }) {
  const sortedList = useMemo(() => {
    return list.sort((a, b) => a.value - b.value);
  }, [list]);

  return <div>{sortedList.map(item => <div key={item.id}>{item.value}</div>)}</div>;
}

2. 主要 Hooks 的使用场景

2.1 useState - 状态管理

适用于管理组件内部状态,替代 class 组件的 this.state。

function Form() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  return (
    <form>
      <input value={name} onChange={e => setName(e.target.value)} />
      <input value={email} onChange={e => setEmail(e.target.value)} />
    </form>
  );
}

2.2 useEffect - 副作用处理

处理数据获取、订阅、手动修改 DOM 等副作用操作,可以替代 componentDidMount、componentDidUpdate 和 componentWillUnmount。

function DataFetcher({ id }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    let isMounted = true;
    
    fetch(`/api/data/${id}`)
      .then(res => res.json())
      .then(data => isMounted && setData(data));

    return () => { isMounted = false; };
  }, [id]); // 依赖项变化时重新执行

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

2.3 useContext - 跨组件共享状态

简化 context 的使用,避免多层组件传递 props。

const ThemeContext = React.createContext('light');

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

function Toolbar() {
  const theme = useContext(ThemeContext);
  return <div style={{ background: theme === 'dark' ? '#333' : '#FFF' }}>Current theme: {theme}</div>;
}

2.4 useReducer - 复杂状态逻辑

适用于状态逻辑较复杂或包含多个子值的场景,是 useState 的替代方案。

function todosReducer(state, action) {
  switch (action.type) {
    case 'add':
      return [...state, { text: action.text, completed: false }];
    case 'toggle':
      return state.map((todo, i) => 
        i === action.index ? {...todo, completed: !todo.completed} : todo
      );
    default:
      return state;
  }
}

function TodoList() {
  const [todos, dispatch] = useReducer(todosReducer, []);

  return (