MST

星途 面试题库

面试题:React中useEffect模拟生命周期时如何避免内存泄漏

在React中,我们常用useEffect来模拟生命周期方法。假设你正在使用useEffect模拟componentDidMount和componentWillUnmount,举例说明在这个过程中可能会出现内存泄漏的场景,并阐述如何避免这种内存泄漏。
27.8万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

可能出现内存泄漏的场景

  1. 异步操作未清理
    • 例如在useEffect模拟componentDidMount时发起一个fetch请求:
    import React, { useEffect } from'react';
    
    const MyComponent = () => {
      useEffect(() => {
        const controller = new AbortController();
        const signal = controller.signal;
        fetch('https://example.com/api/data', { signal })
         .then(response => response.json())
         .then(data => console.log(data));
        return () => {
          controller.abort();
        };
      }, []);
    
      return <div>My Component</div>;
    };
    
    export default MyComponent;
    
    • 如果没有在useEffect返回的清理函数中取消这个fetch请求(即controller.abort()),当组件卸载时,这个fetch请求可能仍在后台执行,占用资源,造成内存泄漏。
  2. 事件监听未移除
    • 假设在useEffect模拟componentDidMount时添加一个全局事件监听:
    import React, { useEffect } from'react';
    
    const MyComponent = () => {
      useEffect(() => {
        const handleScroll = () => {
          console.log('Window scrolled');
        };
        window.addEventListener('scroll', handleScroll);
        return () => {
          window.removeEventListener('scroll', handleScroll);
        };
      }, []);
    
      return <div>My Component</div>;
    };
    
    export default MyComponent;
    
    • 如果没有在清理函数中移除这个事件监听(即window.removeEventListener('scroll', handleScroll)),即使组件已经卸载,handleScroll函数仍然会被调用,占用内存,导致内存泄漏。

避免内存泄漏的方法

  1. 清理异步操作
    • 对于fetch请求等异步操作,使用AbortController来取消操作。如上面第一个例子,在useEffect返回的清理函数中调用controller.abort(),确保在组件卸载时取消未完成的请求。
  2. 移除事件监听
    • 对于添加的事件监听,在useEffect返回的清理函数中使用相应的移除方法。如在添加window.addEventListener后,在清理函数中使用window.removeEventListener移除监听,确保组件卸载时不再响应这些事件,避免内存泄漏。