# 函数组件 vs 类组件

URL: https://caijiao.org/react/chapter4/component-types
Source: docs/react/chapter4/component-types.md
Description: 函数组件和类组件是 React 中两种定义组件的方式。随着 React 发展，函数组件逐渐成为主流，它们更简洁且易于管理状态和副作用。

在 React 中，组件是构建用户界面的基本单位。React 提供了两种定义组件的方式：函数组件和类组件。随着 React 的发展，函数组件逐渐取代了类组件，成为了主流。

## 1. 类组件

类组件是 React 的传统组件定义方式，通常继承自 `React.Component` 类，并且必须有 `render()` 方法来返回 UI 元素。类组件能够使用 `state` 和生命周期方法。

### 1.1 类组件示例

```jsx
import React, { Component } from 'react';

class MyClassComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 };
  }

  handleClick = () => {
    this.setState({ counter: this.state.counter + 1 });
  }

  render() {
    return (
      <div>
        <p>Counter: {this.state.counter}</p>
        <button onClick={this.handleClick}>Increment</button>
      </div>
    );
  }
}

export default MyClassComponent;
````

在类组件中，状态（`state`）通常在构造函数中初始化，且 `this.setState()` 用于更新状态。类组件也可以使用各种生命周期方法，如 `componentDidMount`、`componentDidUpdate` 等。

## 2. 函数组件

函数组件是 React 的新推荐组件定义方式，它是一个普通的 JavaScript 函数，接受 `props` 作为参数并返回要渲染的 JSX。函数组件更简洁，且与类组件相比，易于理解和维护。

### 2.1 函数组件示例

```jsx
import React, { useState } from 'react';

function MyFunctionComponent() {
  const [counter, setCounter] = useState(0);

  const handleClick = () => {
    setCounter(counter + 1);
  };

  return (
    <div>
      <p>Counter: {counter}</p>
      <button onClick={handleClick}>Increment</button>
    </div>
  );
}

export default MyFunctionComponent;
```

在函数组件中，我们通过 React Hook `useState` 来管理组件的状态。与类组件相比，函数组件通常更简洁，不需要写类构造函数和 `this`。

## 3. 主要区别

### 3.1 语法差异

* **类组件**：需要 `render()` 方法，且使用 `this` 来访问组件的状态和方法。
* **函数组件**：是一个普通函数，直接返回 JSX，且不需要 `this`，通过 Hooks（如 `useState`、`useEffect`）来管理状态和副作用。

### 3.2 状态管理

* **类组件**：通过 `this.state` 和 `this.setState()` 来管理状态。
* **函数组件**：通过 `useState` 钩子来管理状态。

### 3.3 生命周期

* **类组件**：提供传统的生命周期方法，如 `componentDidMount`、`componentDidUpdate`、`componentWillUnmount` 等。
* **函数组件**：使用 `useEffect` 钩子代替生命周期方法，`useEffect` 可以在组件挂载时、更新时或卸载时运行代码。

### 3.4 性能和简洁性

* **类组件**：更为冗长，且由于需要继承 `React.Component`，语法较为复杂。
* **函数组件**：更加简洁，使用 Hooks 后可以以更少的代码实现相同功能，性能上也有一定优势（尤其是在 React 16.8 之后，React 对函数组件的优化越来越好）。

## 4. Hooks：函数组件的优势

React 16.8 引入了 Hooks，它让函数组件也能够使用状态和副作用管理功能。常用的 Hooks 包括：

* `useState`：用于管理状态。
* `useEffect`：用于处理副作用（如网络请求、事件监听等）。
* `useContext`：用于使用上下文（Context）API。

### 4.1 使用 Hooks 使函数组件功能更强大

```jsx
import React, { useState, useEffect } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);

    return () => clearInterval(interval);  // 清理副作用
  }, []); // 空依赖数组，表示只在组件挂载和卸载时执行

  return <p>Timer: {seconds} seconds</p>;
}

export default Timer;
```

通过 `useEffect` 钩子，我们在函数组件中实现了定时器，显示时间的递增。这些功能在类组件中通常需要通过生命周期方法来实现。

## 5. 总结

虽然类组件依然可以使用，但 React 团队推荐优先使用函数组件，特别是自从 React 引入了 Hooks 之后，函数组件在处理状态和副作用时变得非常强大。函数组件的简洁性和灵活性使它们成为了 React 开发中的主流。
