告别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

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

相关推荐
LaughingZhu3 小时前
Product Hunt 每日热榜 | 2026-05-21
前端·人工智能·经验分享·chatgpt·html
怕浪猫3 小时前
Electron 开发实战(一):从零入门核心基础与环境搭建
前端·electron·ai编程
小鹏linux3 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
前端若水4 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
Bigger4 小时前
mini-cc:一个轻量级 AI 编程助手的诞生
前端·ai编程·claude
涵涵(互关)5 小时前
Naive-ui树型选择器只显示根节点
前端·ui·vue
BY组态5 小时前
Ricon组态系统最佳实践:从零开始构建物联网监控平台
前端·物联网·iot·web组态·组态
BY组态5 小时前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·物联网·iot·web组态·组态
SoaringHeart5 小时前
Flutter进阶:OverlayEntry 插入图层管理器 NOverlayZIndexManager
前端·flutter
放下华子我只抽RuiKe55 小时前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架