๐ป ์ข๋น ์ปดํฌ๋ํธ: Unmount ๋์ง ์์ ๋น๋๊ธฐ ๊ตฌ๋ ๊ณผ ๋ฉ๋ชจ๋ฆฌ ๋์
Summary
์ปดํฌ๋ํธ unmount ์ ๋น๋๊ธฐ ๊ตฌ๋
์ ์ ๋ฆฌํ์ง ์์ ๋ฐ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํด์ผ ํฉ๋๋ค. useEffect
ํด๋ฆฐ์
ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ฆฌํ์ธ์.
Why Wrong?
์ปดํฌ๋ํธ๊ฐ unmount๋ ํ์๋ ์ฌ์ ํ ์คํ ์ค์ธ ๋น๋๊ธฐ ์์
(์: setInterval
, setTimeout
, RxJS Observable ๊ตฌ๋
, fetch)์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐ์์ํค๊ณ , ์์์น ๋ชปํ ๋ถ์์ฉ์ ์ด๋ํ ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ๊ฐ ๋ ์ด์ ์กด์ฌํ์ง ์์์๋ ๋ถ๊ตฌํ๊ณ ์ด์ ์ํ๋ฅผ ์
๋ฐ์ดํธํ๋ ค๊ณ ์๋ํ๊ฑฐ๋, ์ด๋ฏธ ํด์ ๋ ๋ฆฌ์์ค๋ฅผ ์ฐธ์กฐํ๋ ค ํ ๋ ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ฌํ '์ข๋น ์ปดํฌ๋ํธ'๋ ์ฑ ์ฑ๋ฅ์ ์ ํ์ํค๊ณ , ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง์น ์ ์์ต๋๋ค.
How to Fix?
์ปดํฌ๋ํธ๊ฐ unmount๋ ๋ ๋ชจ๋ ๋น๋๊ธฐ ์์
์ ์ ๋ฆฌํด์ผ ํฉ๋๋ค. useEffect
ํ
์ ํด๋ฆฐ์
ํจ์๋ฅผ ์ฌ์ฉํ์ฌ setInterval
, setTimeout
์ ํด์ ํ๊ณ , RxJS Observable ๊ตฌ๋
์ ์ทจ์ํ๋ฉฐ, ์งํ ์ค์ธ fetch ์์ฒญ์ ์ค๋จํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ณ , ์ปดํฌ๋ํธ๊ฐ unmount๋ ํ ๋ถํ์ํ ์ํ ์
๋ฐ์ดํธ๋ ๋ถ์์ฉ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
Before Code (Bad)
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [data, setData] = useState(null);
useEffect(() => {
const intervalId = setInterval(() => {
fetch('/api/data')
.then(response => response.json())
.then(newData => {
setData(newData);
});
}, 1000);
// ํด๋ฆฐ์
ํจ์๊ฐ ์์! ์ปดํฌ๋ํธ๊ฐ unmount ๋์ด๋ interval์ ๊ณ์ ์คํ๋จ
}, []);
return <div>{data ? data.value : 'Loading...'}</div>;
}
export default MyComponent;
After Code (Good)
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [data, setData] = useState(null);
useEffect(() => {
let isMounted = true; // ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋์ด ์๋์ง ์ถ์
const intervalId = setInterval(() => {
fetch('/api/data')
.then(response => response.json())
.then(newData => {
if (isMounted) { // ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋์ด ์๋ ๊ฒฝ์ฐ์๋ง ์ํ ์
๋ฐ์ดํธ
setData(newData);
}
});
}, 1000);
return () => {
clearInterval(intervalId); // ์ปดํฌ๋ํธ unmount ์ interval ํด์
isMounted = false; // ์ปดํฌ๋ํธ๊ฐ unmount๋์์์ ํ์
};
}, []);
return <div>{data ? data.value : 'Loading...'}</div>;
}
export default MyComponent;