Reaccionar JS. Advertencia: no se puede realizar una actualización del estado Reaccionar en un componente desmontado. Esto es un no-op, pero indica un memo.

Buen dia, Habr!

Todos los desarrolladores de reactjs que se ocupan de la interactividad entre el frente y el frente se encuentran tarde o temprano, o se han encontrado o encontrarán el siguiente error:


Literalmente, resulta así:
Advertencia. No se puede actualizar el estado Reaccionar para un componente desinstalado. Esta no es una operación, pero indica una pérdida de memoria en su aplicación. Para solucionarlo, cancele todas las suscripciones y tareas asincrónicas en la función de limpieza useEffect.

De hecho, todo es bastante simple, solo debes prestar atención a las siguientes frases:

  1. No se puede realizar la actualización de estado
  2. un componente desinstalado;
  3. cancelar todas las suscripciones y tareas asincrónicas
  4. useEffect cleanup


En el corazón de los ganchos. ¡Entra bajo el corte!

Entonces:

  1. Todos los programadores de reactjs saben qué condición (estado) y que tal actualización (setState) también. No seré eso.
  2. . :
    1) ;
    2) ;
    3) ;
    — 3 . .
  3. . - , : . , async/await — .
  4. useEffect. return () => {} useEffect. , - , : .




Cometámonos un error: digamos que estamos desarrollando un sitio con una carga de descripción de película (no profundizaremos en la API moviedb , pero tomaremos una película específica como base). Tenemos dos paginas:
Casa

Sobre nosotros



Los enlaces a ambas páginas están disponibles en el panel de navegación, por ejemplo, en el encabezado. En la página principal ("Inicio") hay comunicación con la parte posterior para cargar información sobre la película.

/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;


Para mostrar información a través de una solicitud, es necesario escribir información en el estado para su posterior representación:

/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;


Reproduciremos el error de la siguiente manera: cambiaremos de una ruta a otra, es decir, al estar en la página "Acerca de nosotros", iremos a la página "Inicio" e inmediatamente volveremos a la página "Acerca de nosotros" y listo " No se puede realizar ... .. " .

El hecho es que el servidor no responde a las solicitudes al instante, se utiliza la asincronía para reproducir la solicitud en paralelo con las tareas necesarias. Pero en el caso de un retorno rápido a la página Acerca de nosotros, el componente Inicio se desmonta, lo que significa que el estado de este componente se restablecerá, pero la solicitud asincrónica seguirá iniciando setMovie, que ya no está allí y arrojará un error. La mejor solución es prohibir el uso de actualizaciones de estado al desmontar un componente:

/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;


Total:


Todo el código fuente se puede ver aquí: https://gitlab.com/ImaGadzhiev/react-cant-perform

All Articles