ReactJS. Peringatan: Tidak dapat melakukan pembaruan status React pada komponen yang dilepas. Ini adalah no-op, tetapi ini menunjukkan memo

Selamat siang, Habr!

Semua pengembang reaksi yang berurusan dengan interaktivitas antara belakang dan depan bertemu cepat atau lambat, atau telah bertemu, atau akan mengalami kesalahan berikut:


Secara harfiah, ternyata seperti ini:
Peringatan. Tidak dapat memperbarui status Bereaksi untuk komponen yang dihapus. Ini bukan operasi, tetapi ini menunjukkan kebocoran memori di aplikasi Anda. Untuk memperbaikinya, batalkan semua langganan dan tugas-tugas tidak sinkron dalam fungsi pembersihan useEffect.

Faktanya, semuanya cukup sederhana, Anda hanya perlu memperhatikan frasa berikut:

  1. Tidak dapat melakukan pembaruan status
  2. komponen yang dihapus;
  3. batalkan semua langganan dan tugas asinkron
  4. useEffect cleanup


Di jantung kait. PERGI di bawah luka!

Begitu:

  1. Semua programmer bereaksi mengetahui kondisi apa (status) dan pembaruan seperti itu (setState) juga. Saya tidak akan seperti itu.
  2. . :
    1) ;
    2) ;
    3) ;
    — 3 . .
  3. . - , : . , async/await — .
  4. useEffect. return () => {} useEffect. , - , : .




Mari kita membuat kesalahan: Katakanlah kita sedang mengembangkan situs dengan unggahan deskripsi film (kami tidak akan masuk jauh ke dalam API moviedb , tetapi mengambil film tertentu sebagai dasar). Kami memiliki dua halaman:
Rumah

Tentang kami



Tautan ke kedua halaman tersedia di panel navigasi, misalnya, di header. Di halaman utama ("Home") ada komunikasi dengan belakang untuk mengunggah informasi tentang film.

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


Untuk menampilkan informasi melalui permintaan, perlu untuk menulis informasi kepada negara untuk rendering berikutnya:

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


Kami akan mereproduksi kesalahan dengan cara berikut - kami akan beralih dari satu rute ke rute lain, yaitu, berada di halaman "Tentang Kami", kami akan pergi ke halaman "Rumah" dan segera kembali lagi ke halaman "Tentang Kami" dan voila " Tidak dapat melakukan ... .. " .

Faktanya adalah bahwa server tidak menanggapi permintaan secara instan, asynchrony digunakan untuk tetap memainkan permintaan secara paralel dengan tugas-tugas yang diperlukan. Tetapi dalam kasus pengembalian cepat ke halaman Tentang Kami, komponen Beranda tidak di-mount, yang berarti bahwa keadaan untuk komponen ini akan diatur ulang, tetapi permintaan asinkron masih akan meluncurkan setMovie, yang sudah tidak ada lagi dan akan menimbulkan kesalahan. Solusi terbaik adalah melarang penggunaan pembaruan negara ketika melepas komponen:

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


Semua kode sumber dapat dilihat di sini: https://gitlab.com/ImaGadzhiev/react-cant-perform

All Articles