告别Class组件!用useEffect玩转React生命周期

大家好,我是小杨。做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);
}

四、我踩过的那些坑

  1. 无限循环陷阱

    jsx 复制代码
    // 错误示范!
    useEffect(() => {
      setCount(count + 1); // 会触发无限重渲染
    }, [count]);
  2. 异步函数处理

    直接在useEffect里写async会警告,应该这样:

    jsx 复制代码
    useEffect(() => {
      (async () => {
        await doSomething();
      })();
    }, []);
  3. 依赖数组太复杂

    当依赖项是对象/数组时,考虑用useMemo缓存

五、现代React的最佳实践

  1. 尽量将不同逻辑拆分成多个useEffect
  2. 复杂的业务逻辑抽成自定义Hook
  3. 使用eslint-plugin-react-hooks插件避免常见错误

结语

从Class到Hooks的转变,就像是手动挡换自动挡------一开始可能不习惯,但用顺手后真的回不去了!

如果你还在用Class组件写新项目,不妨试试用useEffect来管理副作用。刚开始可能会遇到些小磕绊,但相信我,坚持用一周你就会爱上这种写法。

⭐ 写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

相关推荐
universe_014 分钟前
day22|学习前端ts语言
前端·笔记
teeeeeeemo8 分钟前
一些js数组去重的实现算法
开发语言·前端·javascript·笔记·算法
Zz_waiting.9 分钟前
Javaweb - 14.1 - 前端工程化
前端·es6
掘金安东尼11 分钟前
前端周刊第426期(2025年8月4日–8月10日)
前端·javascript·面试
Abadbeginning12 分钟前
FastSoyAdmin导出excel报错‘latin-1‘ codec can‘t encode characters in position 41-54
前端·javascript·后端
ZXT13 分钟前
WebAssembly
前端
卢叁14 分钟前
Flutter开发环境安装指南
前端·flutter
curdcv_po32 分钟前
Three.js,闲谈3D——智慧XX
前端
古茗前端团队33 分钟前
一次useRouter空值的奇妙追踪
react.js
A5rZ1 小时前
css leak -- justctf 2025 Simple Tasks
前端·css·tensorflow