React Hooks 的优势和使用场景

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

## 核心优势

### 1. 简化组件逻辑
Hooks 允许在不编写 class 的情况下使用 state 和其他 React 特性。通过将组件拆分为更小的函数,使代码更易于理解和维护。

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

// 使用 Hooks 的函数组件
function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

2. 更好的代码复用

通过自定义 Hook 可以提取组件逻辑,使这些逻辑可以轻松地在不同组件之间共享。

// 自定义 Hook
function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  }, [friendID]);

  return isOnline;
}

// 在多个组件中使用
function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);
  return isOnline ? 'Online' : 'Offline';
}

function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);
  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

3. 更直观的副作用管理

useEffect 将生命周期方法(如 componentDidMountcomponentDidUpdatecomponentWillUnmount)统一为一个 API。

useEffect(() => {
  // 相当于 componentDidMount 和 componentDidUpdate
  document.title = `You clicked ${count} times`;
  
  // 返回的函数相当于 componentWillUnmount
  return () => {
    document.title = 'React App';
  };
}, [count]); // 仅在 count 更改时更新

主要使用场景

1. 状态管理

useState 是最基础的 Hook,用于在函数组件中添加局部 state。

function Form() {
  const [name, setName] = useState('Mary');
  const [age, setAge] = useState(25);

  return (
    <>
      <input value={name} onChange={e => setName(e.target.value)} />
      <input value={age} onChange={e => setAge(e.target.value)} />
    </>
  );
}

2. 复杂状态逻辑

useReducer 适用于管理包含多个子值的 state 对象,或者当下一个 state 依赖于之前的 state 时。

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

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

  return (
    <>
      {todos.map((todo, index) => (
        <div key={index}>
          {todo.text}
          <input
            type="checkbox"
            checked={todo.completed}
            onChange={() => dispatch({ type: 'toggle', index })}
          />
        </div>
      ))}
      <button onClick={() => dispatch({ type: 'add', text: 'New todo' })}>
        Add Todo
      </button>
    </>
  );
}

3. 性能优化

useMemouseCallback 可以帮助避免不必要的计算和渲染。

function Parent({ a, b }) {
  // 仅当 a 改变时才会重新计算
  const memoizedValue = use