๊ด€๋ฆฌ ๋ฉ”๋‰ด

Daily Front_Minhhk

[React] memory leak error (useEffect cleanup function)__Can't perform a React state update on an unmounted component. ๋ณธ๋ฌธ

์—๋Ÿฌ

[React] memory leak error (useEffect cleanup function)__Can't perform a React state update on an unmounted component.

Minhhk 2024. 2. 27. 14:42
๐Ÿ“Œ 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.

 

์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋œ ํ›„์— ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ์‹œ๋„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ๋‹ค.

์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ์ง„ํ–‰ ์ค‘์ธ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ทจ์†Œํ•˜๊ฑฐ๋‚˜, ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์ง€์•Š๋„๋ก ํ•ด์•ผํ•œ๋‹ค.

 

 

→ useEffectํ›… ์•ˆ์—์„œ ํด๋ฆฐ์—… ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜๊ธฐ ์ „์— ํ•„์š”ํ•œ ์ •๋ฆฌ ์ž‘์—…!

→ dataFetching ์ดํ›„ ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๊ธฐ ์ „์— ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ฌ์ „ํžˆ ๋งˆ์šดํŠธ๋œ ์ƒํƒœ์ธ์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฌธ์ œ ํ•ด๊ฒฐ

 

 

์ด์ „ ์ฝ”๋“œ

const MSearch = () => {
  const { searchText } = useParams();
  const axiosAuth = useAxiosAuth();
  const [data, setData] = useState([]);
  const [results, setResults] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    if (searchText !== '') {
      const searchRule = async () => {
        setIsLoading(true);
        const response = await axiosAuth({
          method: 'POST',
          url: '/api/~~~',
          data: { searchText },
        });
        setData(response.data);
        setResults(response.data);
        setIsLoading(false);
      };
      searchRule();
    }
  }, [searchText]);

  return ( ... )
}

 

 

 

๋ณ€๊ฒฝ ๋œ ์ฝ”๋“œ

const MSearch = () => {
  const { searchText } = useParams();
  const axiosAuth = useAxiosAuth();
  const [data, setData] = useState([]);
  const [results, setResults] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    // ๋งˆ์šดํŠธ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ณ€์ˆ˜
    let isMounted = true;

    if (searchText !== '') {
      const searchRule = async () => {
        setIsLoading(true);
        try {
          const response = await axiosAuth({
            method: 'POST',
            url: '/api/~~~',
            data: { searchText },
          });
          if (isMounted) { // ๋งˆ์šดํŠธ๋œ ์ƒํƒœ -> ์—…๋ฐ์ดํŠธ
            setData(response.data);
            setResults(response.data);
            setIsLoading(false);
          }
        } catch (error) {
          console.error(error);
          if (isMounted) { // ๋งˆ์šดํŠธ๋œ ์ƒํƒœ -> ์—๋Ÿฌ
            setIsLoading(false);
          }
        }
      };
      searchRule();
    }

    // + ํด๋ฆฐ์—… ํ•จ์ˆ˜,,, ๋งˆ์šดํŠธ ์ƒํƒœ false
    return () => {
      isMounted = false;
    };
  }, [searchText]);

  return ( ... )
};

 

>>

 

React์˜ useEffect ํ›…์„ ์‚ฌ์šฉํ•  ๋•Œ, ํด๋ฆฐ์—…(clean-up) ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์—ฌ ๋น„๋™๊ธฐ ์ž‘์—…์ด๋‚˜ ๊ตฌ๋…์„ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๊ฒƒ์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜๊ฑฐ๋‚˜ ์žฌ๋žœ๋”๋ง๋˜๊ธฐ ์ „์— ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

์ผ๋ฐ˜์ ์œผ๋กœ useEffect ํ›… ์•ˆ์—์„œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ, ํ•ด๋‹น ์ž‘์—…์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ํด๋กœ์ €๋‚˜ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ์— ์ €์žฅํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋œ ํ›„์— ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์–ธ๋งˆ์šดํŠธ๋˜์—ˆ๋‹ค๋ฉด ์ž‘์—…์„ ์ค‘์ง€ํ•˜๊ฑฐ๋‚˜ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, useEffect ๋‚ด์—์„œ setInterval์„ ์‚ฌ์šฉํ•˜์—ฌ ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜๋ฉด ํ•ด๋‹น setInterval์„ ํด๋ฆฌ์–ด(clear)ํ•ด์•ผ ํ•œ๋‹ค.

 

ํด๋ฆฐ์—… ํ•จ์ˆ˜๋Š” useEffect ํ›…์˜ ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์ •์˜๋˜๋ฉฐ, useEffect ๋‚ด์—์„œ ํด๋ฆฐ์—… ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ ํ•ด์ œ๋  ๋•Œ ํ˜ธ์ถœ๋˜๋ฉฐ, ํด๋ฆฐ์—… ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์ด์ „์— ์„ค์ •ํ•œ ๋ชจ๋“  ์ž‘์—…์„ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, useEffect ๋‚ด์—์„œ ๊ตฌ๋…์„ ์„ค์ •ํ•œ ๊ฒฝ์šฐ, ํด๋ฆฐ์—… ํ•จ์ˆ˜์—์„œ ํ•ด๋‹น ๊ตฌ๋…์„ ํ•ด์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์€ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ ํ•ด์ œ๋  ๋•Œ ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์ด๋‚˜ ๊ตฌ๋…์ด ๋‚จ์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

 

์ •๋ฆฌ > useEffect ๋‚ด์—์„œ setInterval์„ ์‚ฌ์šฉํ•˜์—ฌ ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ,

์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜๋ฉด ํ•ด๋‹น setInterval์„ ํด๋ฆฌ์–ด ํ•ด์•ผํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋งฅ๋ฝ์ด๋‹ค.