大家好,我是小杨。做React开发6年,见证了从Class组件到Hooks的变迁。今天想聊聊如何用useEffect这个"瑞士军刀"来模拟Class组件的生命周期方法。
还记得我刚学React时,生命周期方法是必背口诀:
"willMount、didMount、willUpdate..."
现在有了Hooks,一切都变得更简单了!
一、从Class到Hooks的生命周期映射
先看张对照表,老司机们肯定秒懂:
Class生命周期 | Hooks等效实现 |
---|---|
componentDidMount | useEffect(fn, []) |
componentDidUpdate | useEffect(fn, [dep]) |
componentWillUnmount | useEffect返回清理函数 |
shouldComponentUpdate | useMemo/React.memo |
二、实战代码演示
1. 模拟componentDidMount(只运行一次)
jsx
function MyComponent() {
useEffect(() => {
console.log('组件挂载完成,相当于didMount');
// 这里可以放初始化逻辑
const fetchData = async () => {
const res = await api.getUserInfo();
console.log('我拿到了数据:', res);
};
fetchData();
}, []); // 注意这个空数组!
}
关键点: 依赖数组为空,确保只在挂载时执行
2. 模拟componentDidUpdate(依赖更新时触发)
jsx
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
console.log('userId变化时执行,相当于didUpdate');
const loadUser = async () => {
const data = await api.fetchUser(userId);
setUser(data);
};
loadUser();
}, [userId]); // 这里放依赖项
}
常见坑点: 忘记加依赖数组会导致每次渲染都执行!
3. 模拟componentWillUnmount(清理副作用)
jsx
function ChatRoom() {
useEffect(() => {
const socket = connectToSocket();
return () => {
console.log('组件卸载前执行,相当于willUnmount');
socket.disconnect(); // 清理操作
};
}, []);
}
血泪教训: 不清理定时器/订阅会导致内存泄漏!
三、高级技巧
1. 模拟shouldComponentUpdate
jsx
const MemoizedComponent = React.memo(
function MyComponent(props) {
/* 只有props变化时才会重渲染 */
},
(prevProps, nextProps) => {
// 自定义比较逻辑
return prevProps.value === nextProps.value;
}
);
2. 只在更新时运行(忽略首次渲染)
jsx
function useDidUpdateEffect(fn, deps) {
const didMountRef = useRef(false);
useEffect(() => {
if (didMountRef.current) {
fn();
} else {
didMountRef.current = true;
}
}, deps);
}
四、我踩过的那些坑
-
无限循环陷阱
jsx// 错误示范! useEffect(() => { setCount(count + 1); // 会触发无限重渲染 }, [count]);
-
异步函数处理
直接在useEffect里写async会警告,应该这样:
jsxuseEffect(() => { (async () => { await doSomething(); })(); }, []);
-
依赖数组太复杂
当依赖项是对象/数组时,考虑用useMemo缓存
五、现代React的最佳实践
- 尽量将不同逻辑拆分成多个useEffect
- 复杂的业务逻辑抽成自定义Hook
- 使用eslint-plugin-react-hooks插件避免常见错误
结语
从Class到Hooks的转变,就像是手动挡换自动挡------一开始可能不习惯,但用顺手后真的回不去了!
如果你还在用Class组件写新项目,不妨试试用useEffect来管理副作用。刚开始可能会遇到些小磕绊,但相信我,坚持用一周你就会爱上这种写法。
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!