IT이야기

useEffect를 사용하여 반응 구성 요소의 메모리 누수

cyworld 2022. 3. 28. 21:20
반응형

useEffect를 사용하여 반응 구성 요소의 메모리 누수

나는 "뉴스"를 열면 모달로 된 설명을 볼 수 있고, 완벽히 작동하지만, 제안을 클릭하면 해당 제품에 대한 정보가 있는 다른 페이지로 리디렉션되는 Carrouzel을 하고 있다.

작동하지만 실행하면 콘솔에 메모리 누수 오류 "react-dom.development.js:67 경고: 마운트 해제된 구성 요소에 대해 반응 상태 업데이트를 수행할 수 없음 이것은 작동 불가지만, 당신의 어플리케이션에 메모리 누수가 있다는 것을 나타낸다. 수정하려면 useEffect cleaning 함수의 모든 구독 및 비동기 작업을 취소하십시오.

나는 useEffect를 사용하는 것을 알고 있고 이것을 피하는 방법을 모른다.

시간 내줘서 고마워

"AxiosCollection" 입니다.

import axios from "axios";
const baseURL = "http://localhost:8080";

function AxiosGetData(url, setData) {
  axios
    .get(`${baseURL}${url}`, {
      headers: {
        "Content-type": "application/json",
      },
    })
    .then((response) => {
      setData(response.data);
    })
    .catch((error) => {
      return error;
    });
}

export {
  AxiosGetData
};

import React, { useState, useEffect } from "react";
import { AxiosGetData } from "../AxiosCollection/AxiosCollection";
import Modal from "../Modal/Modal";
import { Link } from "react-router-dom";

// Import Swiper React components
import { Swiper, SwiperSlide } from "swiper/react";

// Import Swiper styles
import "swiper/swiper-bundle.min.css";
import "swiper/swiper.min.css";

import BenefitCard from "../";

//Css file
import "./Slider.css";

// import Swiper core and required modules
import SwiperCore, { Pagination, Navigation } from "swiper";

// install Swiper modules
SwiperCore.use([Pagination, Navigation]);

const Slider = () => {
  //state to populate with featured object from API
  const [featured, setFeatured] = useState([]);
  const [isOpen, setIsOpen] = useState(false);
  const [featuredById, setFeaturedById] = useState();  
  const onCloseRequest = () => setIsOpen(false);

  // hook to fetch data with Axios,it only runs once, takes an url and a function as params
  
  const handleClick = (item) => {
    AxiosGetData(`/jp-coin/featured/${item.featuredId}`, setFeaturedById);
    setIsOpen(true);
  };
  
  useEffect(() => {
    AxiosGetData("/...", setFeatured);
    
  }, []);

  return (
    <Swiper
      slidesPerView={1}
      spaceBetween={30}
      slidesPerGroup={1}
      loop={true}
      loopFillGroupWithBlank={true}
      pagination={{ clickable: true }}
      navigation={true}
      breakpoints={{
        768: {
          slidesPerView: 3,
          spaceBetween: 30,
          slidesPerGroup: 3,
        },
      }}
      className="mySwiper"
    >
      {featured.map((item) => (
        <SwiperSlide key={item.featuredId} onClick={() => handleClick(item)}>
          <Link to={item.type === "offer" ? `/jp-coin/offers/${item.featuredId}` : "/"}>
            <BenefitCard benefit={item} />
          </Link>
        </SwiperSlide>
      ))}
      {featuredById && featuredById.type === "news" && (
        <>
          <Modal
            isOpen={isOpen}
            onCloseRequest={onCloseRequest}
            className="slider__modalContainer"
          >
            <img src={featuredById.image} alt={featuredById.title} />
            <h1 className="slider__modalTitle">{featuredById.title}</h1>
            <p className="slider__modalDescription">
              Lorem ipsum dolor sit, amet consectetur adipisicing elit. Hic
              blanditiis aperiam fuga ex, ratione recusandae ut harum, nam
              doloremque veniam necessitatibus, fugiat delectus placeat possimus
              totam sequi. Minus, at vitae.
            </p>
          </Modal>
        </>
      )}
      ;
    </Swiper>
  );
};

export default Slider;

비동기식으로 상태를 업데이트하려고 하면 구성 요소가 마운트 해제되었을 때 업데이트가 발생할 수 있기 때문이다.

아래 코드와 같이 구성 요소가 장착되었는지 여부를 확인할 수 있는 참조를 보관하십시오.

왜냐하면 그 시행이 보이지 않기 때문이다.AxiosGetData당신은 단지 당신이 언제 공리로부터 약속을 소비할지, ref가 사실인지 확인할 수 있다.

  const isMountedRef = useRef();
  
  useEffect(() => {
    isMountedRef.current = true
    // In your async function check is the isMountedRef is true or not
    AxiosGetData("/jp-coin/featured", setFeatured);
    
    return () => { isMountedRef.current = false }
  }, []);

예를 들어, 정기적인 가져오기를 사용하면 다음과 같이 달성할 수 있다.

  const isMountedRef = useRef();
  
  useEffect(() => {
    isMountedRef.current = true;

    fetch('someAPIDomain').then(data => {
      isMountedRef.current && setState(data);
    });

    return () => { isMountedRef.current = false }
  }, []);

내 생각에 너의 문제는 아마도handleClick아닌 것 같다useEffect항목을 클릭할 때("뉴스" 또는 "오퍼" 유형이 있는지 여부에 관계없이) 클릭 핸들러가 호출함AxiosGetData상태 업데이트를 수행하려고 시도하십시오.setFeatureById그리고setIsOpen모달(모달)을 보여주기 위해.그러나 "오퍼" 항목의 경우 세부사항 페이지로 리디렉션되므로Slider상태 업데이트가 발생하기 전에 구성 요소가 마운트 해제되므로 메모리 누수 경고가 발생할 수 있다."오퍼" 항목에 대해 상태 업데이트가 발생하지 않도록 하려면handleClick다음으로:

  const handleClick = (item) => {
    if (item.type === 'news') {
      AxiosGetData(`/jp-coin/featured/${item.featuredId}`, setFeaturedById);
      setIsOpen(true);
    }
  };

참조URL: https://stackoverflow.com/questions/71055548/memory-leak-in-react-component-using-useeffect

반응형