还记得刚开始学习React时,我总是在类组件和函数组件之间纠结。每次创建新组件都要面临选择困难症:是用传统的类组件,还是尝试新的函数组件?随着Hooks的推出,这种选择变得更加有趣。
今天我想和大家分享这段学习历程,希望能帮助正在面临同样选择的你。
初识类组件:面向对象的思维模式
我最初接触React时,类组件是绝对的主流。那时候的函数组件还被称为"无状态组件",功能相当有限。
jsx
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
username: '小明'
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({ count: this.state.count + 1 });
}
componentDidMount() {
console.log('组件挂载完成!');
}
render() {
return (
<div>
<h1>Hello, {this.state.username}!</h1>
<p>点击次数: {this.state.count}</p>
<button onClick={this.handleClick}>点击我</button>
</div>
);
}
}
这种面向对象的写法对我来说很自然,特别是已经有其他面向对象语言经验的开发者。但随着时间的推移,我也发现了一些痛点:
函数组件的华丽转身
当React Hooks推出后,函数组件彻底改变了我的开发方式:
jsx
function Welcome() {
const [count, setCount] = useState(0);
const [username, setUsername] = useState('小明');
useEffect(() => {
console.log('组件挂载完成!');
}, []);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<h1>Hello, {username}!</h1>
<p>点击次数: {count}</p>
<button onClick={handleClick}>点击我</button>
</div>
);
}
这种写法让我眼前一亮!代码变得如此简洁,再也不用担心this
的绑定问题了。
核心差异对比
1. 代码简洁性
类组件需要更多的样板代码:
jsx
class UserProfile extends React.Component {
constructor(props) {
super(props);
this.state = {
user: null,
loading: true
};
}
async componentDidMount() {
const user = await fetchUser(this.props.userId);
this.setState({ user, loading: false });
}
componentDidUpdate(prevProps) {
if (prevProps.userId !== this.props.userId) {
this.setState({ loading: true });
this.fetchUserData();
}
}
fetchUserData = async () => {
const user = await fetchUser(this.props.userId);
this.setState({ user, loading: false });
};
render() {
if (this.state.loading) return <div>加载中...</div>;
return <div>{this.state.user.name}</div>;
}
}
函数组件用Hooks实现同样的功能:
jsx
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
const userData = await fetchUser(userId);
setUser(userData);
setLoading(false);
};
fetchData();
}, [userId]);
if (loading) return <div>加载中...</div>;
return <div>{user.name}</div>;
}
2. 生命周期管理的不同思路
类组件的生命周期方法:
jsx
class DataFetcher extends React.Component {
componentDidMount() {
// 组件挂载后执行
this.startInterval();
}
componentDidUpdate(prevProps) {
// props更新时执行
if (prevProps.interval !== this.props.interval) {
this.clearInterval();
this.startInterval();
}
}
componentWillUnmount() {
// 组件卸载前清理
this.clearInterval();
}
startInterval = () => {
this.intervalId = setInterval(() => {
this.fetchData();
}, this.props.interval);
};
clearInterval = () => {
clearInterval(this.intervalId);
};
fetchData = () => {
// 获取数据逻辑
};
render() {
return <div>定时器组件</div>;
}
}
函数组件使用Effect Hook:
jsx
function DataFetcher({ interval }) {
useEffect(() => {
const intervalId = setInterval(() => {
fetchData();
}, interval);
// 清理函数
return () => clearInterval(intervalId);
}, [interval]); // 依赖数组
const fetchData = () => {
// 获取数据逻辑
};
return <div>定时器组件</div>;
}
实际开发中的体验差异
逻辑复用方式
在类组件时代,我们使用高阶组件或render props来复用逻辑:
jsx
// 高阶组件方式
function withAuth(WrappedComponent) {
return class extends React.Component {
state = { user: null };
componentDidMount() {
this.checkAuth();
}
checkAuth = async () => {
const user = await checkAuthentication();
this.setState({ user });
};
render() {
return <WrappedComponent user={this.state.user} {...this.props} />;
}
};
}
现在使用自定义Hook:
jsx
// 自定义Hook
function useAuth() {
const [user, setUser] = useState(null);
useEffect(() => {
const checkAuth = async () => {
const userData = await checkAuthentication();
setUser(userData);
};
checkAuth();
}, []);
return user;
}
// 在组件中使用
function UserProfile() {
const user = useAuth();
// ... 组件逻辑
}
性能考量
很多人担心函数组件的性能问题,但React团队做了大量优化。实际上,在现代React版本中,两者性能差异微乎其微。
jsx
// React.memo优化函数组件
const OptimizedComponent = React.memo(function MyComponent({ data }) {
// 组件逻辑
return <div>{data}</div>;
});
// 类组件的PureComponent
class OptimizedClassComponent extends React.PureComponent {
render() {
return <div>{this.props.data}</div>;
}
}
我的选择建议
经过多个项目的实践,我现在更倾向于使用函数组件:
- 新项目:毫不犹豫选择函数组件 + Hooks
- 老项目维护:根据具体情况,逐步迁移到函数组件
- 学习路径:新手可以直接从函数组件开始学习
但类组件仍然有其价值,特别是在维护老项目或某些特殊场景下。
结语
从类组件到函数组件的转变,反映了React生态的演进。函数组件以其简洁性和强大的Hooks能力,为React开发带来了新的活力。
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!