React为什么要使用函数式组件代替类组件?
1.什么是类组件和函数组件?
1.1 类组件
类组件就是基于ES6语法定义,需要继承React.compoent实现,是react早期的组件定义形式
示例代码:
javascript
import React from 'react';
class Counter extends React.Component {
// 初始化状态
state = { count: 0 };
// 事件处理方法
handleIncrement = () => {
// 更新状态(触发重新渲染)
this.setState({ count: this.state.count + 1 });
};
// 生命周期方法:组件挂载后执行
componentDidMount() {
console.log('组件已挂载');
}
// 渲染 UI
render() {
return (
<div>
<p>计数:{this.state.count}</p>
<button onClick={this.handleIncrement}>+1</button>
</div>
);
}
}
export default Counter;
代码特征:
- 需要使用class关键字,需要继承React.Component
- 强依赖this关键字访问数据,this.state管理内部状态,this.setState来触发状态更新和组件渲染
- 强依赖生命周期,手动实现在什么阶段干什么事情这一内容
1.2 函数式组件
以javascript函数形式定义组件
javascript
import React, { useState, useEffect } from 'react';
// 函数组件接收 props(可选)
const Counter = (props) => {
// 通过 useState 管理状态(替代 this.state 和 this.setState)
const [count, setCount] = useState(0);
// 事件处理函数(无需绑定 this)
const handleIncrement = () => {
setCount(count + 1); // 更新状态(触发重新渲染)
};
// 通过 useEffect 处理副作用(替代生命周期方法)
useEffect(() => {
console.log('组件已挂载或 count 变化');
// 组件卸载时执行清理逻辑(替代 componentWillUnmount)
return () => console.log('组件将卸载');
}, [count]); // 依赖数组:仅当 count 变化时执行
// 直接返回 UI(无需 render() 方法)
return (
<div>
<p>计数:{count}</p>
<button onClick={handleIncrement}>+1</button>
</div>
);
};
export default Counter;
代码特征:
- 本质是一个普通函数,接收
props
作为参数,返回 JSX。(符合react的函数式原则,UI = f(props)) - 早期(无 Hooks 时)只能是 "无状态组件"(仅依赖
props
渲染,无法管理内部状态),引入 Hooks 后可通过useState
管理状态,通过useEffect
处理副作用。 - 无需
this
关键字,直接通过函数参数获取props
,逻辑独立,不依赖组件本身
2.为什么react后期逐渐使用函数式组件来代替类组件?
2.1 设计理念
类组件:对应的是面向对象的设计理念
函数式组件:对应的是函数式编程的设计理念

我们开发者编写的代码,应该是声明式的代码,即数据是如何变化的代码
然后react框架的工作应该是,把声明式的代码,转换成命令式的DOM操作
即数据和渲染是强绑定的
但是,类组件对这方面具有其局限性
2.2 类组件的局限性
2.2.1 类组件的数据和渲染存在天然的割裂
因为类组件强依赖于this的指向,对于react的设计理念来说,应该无论如何,输入一个data,都应该可以准确的渲染到ui上面去,但是由于this指向的可变性,导致如果this的绑定错误的话,数据的变化无法准确的反映在页面上面,这不符合函数式设计的理念
2.2.2 类组件具有命令式编程的痕迹
react推崇的声明式编程,开发者应该只关心(UI是什么样的),而不必关心(如何通过DOM操作来实现这种变化)
但是类组件的生命周期的设计,使得开发者需要去做这样一件事情(开发者需要手动去控制在什么时机执行什么事情)
取而代之,函数式+hook的做法更贴合声明式,useEffect这个hook,可以实现当依赖变化的时候自动更新UI,无需开发者手动关心时机,只需要描述UI与数据的依赖关系
2.2.3 类组件使逻辑强依赖组件,无法抽离逻辑本身
ini
class UserForm extends React.Component {
state = { username: '', password: '', error: '' };
// 事件处理逻辑
handleInputChange = (e) => { ... };
// 数据验证逻辑
validateForm = () => { ... };
// API 请求逻辑
submitForm = async () => { ... };
render() { ... }
}
比如上述这段代码,一个组件里面的所有逻辑,都与组件物理绑定,通过state绑定,无法抽离
php
// 抽离的验证逻辑(完全独立,不依赖任何组件)
function useFormValidation(initialValues) {
const [values, setValues] = useState(initialValues);
const [error, setError] = useState('');
const validate = () => {
if (!values.username) setError('用户名不能为空');
// ... 其他验证逻辑
};
return { values, setValues, error, validate };
}
// 在组件中复用
function UserForm() {
const { values, setValues, error, validate } = useFormValidation({ username: '', password: '' });
// ... 直接使用复用的逻辑
}
// 另一个组件也能复用
function ProfileForm() {
const { values, setValues, error, validate } = useFormValidation({ name: '', age: '' });
// ...
}
而对于函数式组件来说,可以抽离逻辑,在多个组件进行复用
2.2.4 类组件封装的内容过于庞大
类组件通常内部已经封装好了许多内容,比如各种生命周期,但对于一些简单的组件,从头编写一个类组件显得十分繁杂,许多内容不是必须项