ReactJS。警告:无法在已卸载的组件上执行React状态更新。这是空操作,但表示有备忘

美好的一天,哈伯!

所有处理后端和前端之间交互性的reactjs开发人员迟早会面,或者已经见面,或者会遇到以下错误:


从字面上看,结果是这样的:
警告。无法更新已卸载组件的React状态。这不是一项操作,但是它表明您的应用程序中发生内存泄漏。要修复,请取消useEffect清理功能中的所有订阅和异步任务。

实际上,一切都非常简单,您只需要注意以下短语:

  1. 无法执行状态更新
  2. 未安装的组件;
  3. 取消所有订阅和异步任务
  4. useEffect清理


在挂钩的心脏。快进去!

所以:

  1. 所有reactjs程序员都知道什么条件(状态)以及这样的更新(setState)。我不会那样。
  2. . :
    1) ;
    2) ;
    3) ;
    — 3 . .
  3. . - , : . , async/await — .
  4. useEffect. return () => {} useEffect. , - , : .




让我们 重现该错误:假设我们正在开发一个加载电影描述的网站(我们不会深入到moviedb API,而是以特定电影为基础)。我们有两个页面:

关于我们



导航面板(例如,标题)中提供了指向这两个页面的链接。在主页(“主页”)上,与背面进行通讯以下载有关电影的信息。

/src/Pages/HomePage.js
import React, { useState, useEffect } from 'react';

import { MOVIE_DB_GET } from '../config';

const HomePage = () => {
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(MOVIE_DB_GET);
        const result = await response.json();
        console.log(result, 'result')
      } catch (e) {
        console.error(e.message)
      }
    };

    //  get-     
    fetchData();
  }, []);

  return (
    <main>
      <h2> </h2>
    </main>
  )
};

export default HomePage;


/src/Pages/AboutPage.js

import React from 'react';

const AboutPage = () => {
  return (
    <main>
      <h2> </h2>
      <p>
                
      </p>
    </main>
  )
};

export default AboutPage;


要通过请求显示信息,必须将信息写入状态以进行后续呈现:

/src/Pages/HomePage.js

import React, { useState, useEffect } from 'react';

import { MOVIE_DB_GET } from '../config';

const HomePage = () => {
  // movie - react-;
  // setMovie -   react-
  const [ movie, setMovie ] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(MOVIE_DB_GET);
        const result = await response.json();
        console.log(result, 'result');
        setMovie(result);
      } catch (e) {
        console.error(e.message)
      }
    };

    //       
    fetchData();
  }, []);

  // descriptionMovie -  ,  view,         movie

  return (
    <main>
      <h2> </h2>
      <p> </p>

      {
        movie ? descriptionMovie() : false
      }
    </main>
  )
};

export default HomePage;


我们将通过以下方式重现错误-我们将从一条路线切换到另一条路线,即,在“关于我们”页面上,我们将转到“主页”页面,然后立即再次返回到“关于我们”页面,瞧,“ 无法执行..... ” 。

事实是服务器不会立即响应请求,异步仍用于与必要任务并行播放请求。但是,如果要快速返回到“关于我们”页面,则会卸载Home组件,这意味着将重置该组件的状态,但是异步请求仍将启动setMovie,而该setMovie不再存在并且将引发错误。最好的解决方案是在卸载组件时禁止使用状态更新:

/src/Pages/HomePage.js

import React, { useState, useEffect } from 'react';

import { MOVIE_DB_GET } from '../config';

const HomePage = () => {
  // movie - react-;
  // setMovie -   react-
  const [ movie, setMovie ] = useState(null);

  useEffect(() => {
    let cleanupFunction = false;
    const fetchData = async () => {
      try {
        const response = await fetch(MOVIE_DB_GET);
        const result = await response.json();
        console.log(result, 'result')

        //     ,    
        if(!cleanupFunction) setMovie(result);
      } catch (e) {
        console.error(e.message)
      }
    };

    fetchData();

    //   useEffect
    return () => cleanupFunction = true;
  }, []);

  // descriptionMovie -  ,  view,         movie

  return (
    <main>
      <h2> </h2>
      <p> </p>

      {
        movie ? descriptionMovie() : false
      }
    </main>
  )
};

export default HomePage;


总:


可以在这里查看所有源代码:https//gitlab.com/ImaGadzhiev/react-cant-perform

All Articles