【问题标题】:ReactJS memory leak while async tasks & subscriptions异步任务和订阅时 ReactJS 内存泄漏
【发布时间】:2019-06-12 12:11:44
【问题描述】:

在我的反应应用程序中,我正在使用 axios 进行 API 调用。但是,在我的控制台中,我得到了一个错误 “警告:无法对未安装的组件执行 React 状态更新。这是一个无操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 componentWillUnmount 方法中的所有订阅和异步任务。” 我的代码如下

为了修复内存泄漏,我添加了 _isMounted 检查并安慰了 _ismounted。我的应用程序被渲染了两次。 第一次控制台打印 _isMounted 状态为 true,然后为 false(由于 componentDidMount),但随后第二次呈现应用程序,并且控制台中的 _isMounted 打印为 true。

app.jsx
export class Test extends Component {
_isMounted = false;
  constructor(props) {
    super(props);
    this.state = {
      apiData: null
    }
  }
  componentDidMount() {
    this._isMounted = true;
    API.callAPI(this.setStateHandler, this._isMounted)
  }
  setStateHandler = (state) => {
    this.setState(state);
  }
 componentWillUnmount() {
    this._isMounted = false
  }
 render() {
  return(...)}

api.js
callAPI = (setStateHandler, _isMounted) => {
    axios.get('/article', {headers: {Authorization: token}})
    .then((response) => {
      if(_isMounted) {
        setStateHandler({ programs: response.data.data.programs });
      }
    })
  }
  1. 我想解决我的内存泄漏问题。我应该如何解决这个问题?
  2. 为什么我的应用程序渲染了两次,而第二次没有调用 componentDidUnmount?

我将不胜感激。

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    当您的组件卸载时,传递给callAPI_isMounted 参数不会改变。

    您可以改为将数据返回到组件并检查 this._isMounted 是否仍然存在 true

    示例

    // App.jsx
    export class Test extends Component {
      _isMounted = false;
      state = { programs: null };
    
      componentDidMount() {
        this._isMounted = true;
    
        API.callAPI().then(data => {
          if (this._isMounted) {
            this.setState({ programs: data.data.programs });
          }
        });
      }
    
      componentWillUnmount() {
        this._isMounted = false;
      }
    
      render() {
        // ...
      }
    }
    
    // api.js
    const callAPI = () => {
      return axios
        .get("/article", { headers: { Authorization: token } })
        .then(response => response.data);
    };
    

    【讨论】:

    • 感谢您回答@Tholle ...内存泄漏问题已得到修复。但是我的应用程序渲染了 3 次。第一次渲染(),didMount()和WillUnmount()正在运行,然后渲染(),DidMount()和第三次渲染应用程序被完全渲染。这正常吗……渲染3次?
    • @TEMP 太好了!您至少必须渲染 2 次:初始渲染,以及在 callAPI 回调中执行 setState 时的第二次渲染。我不确定第三个渲染是从哪里来的,如果不看更多代码就很难判断。不过我不会担心的。
    • Ok ... @Tholle 我正在使用 _isMounted 这是内存泄漏的已弃用解决方案。你能建议我任何其他解决方案吗?谢谢,抱歉问了另一个问题
    • @TEMP 使用函数 this.isMounted() 已被弃用,但像您一样存储一个实例变量,例如调用_isMounted_isAlive 或任何你喜欢的仍然是一个有效的解决方案。如果您仍然不确定它是否好,请考虑打开另一个问题,因为该问题已得到回答。
    猜你喜欢
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多