简体   繁体   中英

useEffect cleanup function with Firebase and React

I have an issue where my useEffect is causing the following warning:

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

The issue only shows up when reloading the page starting from the page where this component is active..

The component works all well, but the warning looks quite bad.

I'v seen multiple posts where using a clean-up function should work, and tried to apply, but it keeps giving me the same warning.

Any clues?

import React, { useState, useEffect } from 'react'
import ImageGallery from 'react-image-gallery';
import "./ImageGal.css"
import "react-image-gallery/styles/css/image-gallery.css";
import fire from "./firebase";

function ImageGal({ unique }) {

    const [images, setImages] = useState([]);    

    useEffect(() => {
        const fetchImages = async () => {
            const response = fire.firestore().collection("albums/" + unique + "/images"); //unique is the name of the album, passed on as a prop to this component
            const data = await response.get();
            const Imagearray = [];

            data.docs.forEach(item => {
                Imagearray.push({ id: item.id, original: item.data().url })
            })
            setImages(Imagearray)
        }

        fetchImages();

    }, [])


    return (
        <div className="imagegal">

            <ImageGallery
                infinite={true}
                lazyLoad={true} items={images} showThumbnails={false}
                slideInterval={4000}

            />
        </div>
    )
}

export default ImageGal

Best regards, Oscar

The issue is that the component unmounts but you try to set state after that happens. The easiest way to prevent this is to have an isMounted variable set to true that, in your cleanup function, you set to false . Then, only set the state in your effect if that variable is true .

useEffect(() => {
  let isMounted = true;

  const fetchImages = async () => {
    const response = fire
      .firestore()
      .collection("albums/" + unique + "/images"); //unique is the name of the album, passed on as a prop to this component
    const data = await response.get();
    const Imagearray = [];

    data.docs.forEach((item) => {
      Imagearray.push({ id: item.id, original: item.data().url });
    });

    if (isMounted) setImages(Imagearray);
  };

  fetchImages();

  return () => {
    isMounted = false;
  };
}, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM