๐ ์ธ์ useEffect๋ฅผ ์ฌ์ฉํ๋์?
์ด๋ค ์ปดํฌ๋ํธ๊ฐ
- Mount ๋์์ ๋ (ํ๋ฉด์ ์ฒซ ๋ ๋๋ง)
- Update ๋์์ ๋ (๋ค์ ๋ ๋๋ง)
- Unmount ๋์์ ๋ (ํ๋ฉด์์ ์ฌ๋ผ์ง)
useEffect
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๐ useEffect ์ฌ์ฉ ๋ฐฉ๋ฒ
[๋น ๋ฐฐ์ด]
useEffect
๋ ์ธ์๋ก ์ฝ๋ฐฑํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
useEffect(()=>{
// ์์
});
์ด๋ฐ ํํ๋ก ์ฌ์ฉํ๋ค๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ, ์ ๋ฐ์ดํธ๋ ๋ ์คํ๋ฉ๋๋ค.
[์์กด์ฑ ๋ฐฐ์ด]
useEffect(()=>{
// ์์
}, [value]);
์ด๋ ๊ฒ ์ธ์๋ก ๋ฐฐ์ด์ ์ ๋ฌํ๋ค๋ฉด, ๋งค๋ฒ ๋ ๋๋ง์ด ๋ ๋๋ง๋ค ์คํ๋์ง ์๊ณ ๋ง์ดํธ๋ ๋์ ๋ฐฐ์ด value
๊ฐ์ด ๋ฐ๋ ๋ ๋ง๋ค ์คํ๋ฉ๋๋ค. ๋ง์ฝ ๋น ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋งจ ์ฒ์ ํ๋ฉด์ ๋ ๋๋ง๋ ๋๋ง ์คํ๋ฉ๋๋ค.
Clean up: return ๊ฐ
useEffect(() => {
// ํ์ด๋จธ ๊ธฐ๋ฅ...
return () => {
// ํ์ด๋จธ ํด์ ...
// Clean Up (์ ๋ฆฌ)) ์์
์ฒ๋ฆฌ
};
}, []);
์ด๋ ๊ฒ ํจ์๋ฅผ ๋ฆฌํดํด์ฃผ๋ฉด ํด๋น ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋, ํน์ ๋ค์ ๋ ๋๋ง ์ useEffect๊ฐ ์คํ๋๊ธฐ ์ ์ ํจ์๊ฐ ์คํ๋ฉ๋๋ค. ์์ ์ฝ๋์์๋ ์์๋ก ํ์ด๋จธ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ณ ๋ฆฌํด๊ฐ์ผ๋ก ํ์ด๋จธ ํด์ ๋ผ๋ ์ ๋ฆฌ ์์ ์ฝ๋๋ฅผ ๋ฃ๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํ์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์ง์ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
โญ๏ธ useEffect: ์นด์ดํฐ ์ค์ต
useState
Update ๋ฒํผ์ ๋๋ฅด๋ฉด count๊ฐ 1์ฉ ์ฆ๊ฐํ๋ ์นด์ดํฐ ์ฝ๋๋ฅผ ์์ฑํ์ต๋๋ค. useState๋ฅผ ์ด์ฉํด count๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
const App = () => {
const [count, setCount] = useState(0);
const handledCountUpdate = () => {
setCount(count + 1);
};
return (
<div>
<button onClick={handledCountUpdate}>Update</button>
<h3>count: {count}</h3>
</div>
);
};
export default App;
์ด์ ์ด ์ฝ๋์์ useEffect๋ฅผ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.
// ๋ ๋๋ง ๋ ๋๋ง๋ค ๋งค๋ฒ ์คํ๋จ
useEffect(() => {
console.log("๐ฅณ ๋ ๋๋ง๋์์ต๋๋ค!");
});
๋ ๋๋ง ๋ ๋๋ง๋ค ์ ๋ง ๋งค๋ฒ ์คํ๋๋์ง ํ์ธํ๊ธฐ ์ํ์ฌ ์ฝ์๋ก ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
์ค์ ๋ก ์ฒ์ ๋ ๋๋ง๋ ๋, ๊ทธ๋ฆฌ๊ณ state๊ฐ ์ ๋ฐ์ดํธ๋ ๋๋ง๋ค ์ฝ์์ ๋ ๋๋ง๋์๋ค๋ ๋ฉ์ธ์ง๊ฐ ๊ณ์ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด์ input ํ๊ทธ์ ํจ๊ป name์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋ง ํด๋ณด๊ฒ ์ต๋๋ค.
const App = () => {
const [count, setCount] = useState(0);
const [name, setName] = useState("");
const handledCountUpdate = () => {
setCount(count + 1);
};
const handleInputChange = (e) => {
setName(e.target.value);
};
// ๋ ๋๋ง ๋ ๋๋ง๋ค ๋งค๋ฒ ์คํ๋จ
useEffect(() => {
console.log("๐ฅณ ๋ ๋๋ง๋์์ต๋๋ค!");
});
return (
<div>
<button onClick={handledCountUpdate}>Update</button>
<h3>count: {count}</h3>
<input type="text" value={name} onChange={handleInputChange} />
<span>name: {name}</span>
</div>
);
};
export default App;
input์์ ๊ฐ์ ์ ๋ ฅํ ๋๋ง๋ค ๋ ๋๋ง๋์๋ค๊ณ ์ถ๋ ฅ๋๊ณ ์์ต๋๋ค. ๋ฟ๋ง ์๋๋ผ ์นด์ดํธ๋ฅผ ์ ๋ฐ์ดํธ ํ ๋ ์ญ์ ๋ ๋๋ง ๋ฉ์ธ์ง๊ฐ ์ฌ์ ํ ์ถ๋ ฅ๋ฉ๋๋ค. ์ฆ, ์ด ์ฝ๋๋ useEffect๋ฅผ ๋ ๋๋ง๋ ๋๋ง๋ค ์คํํ๊ณ ์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ง์ฝ ๋จ์ํ console.log๋ก ๋ฉ์ธ์ง๋ฅผ ์ถ๋ ฅํ๋ ๊ฒ์ด ์๋๋ผ, ๋ฌด๊ฑฐ์ด ์์ ์ ๋ฃ๋๋ค๋ฉด ๋นํจ์จ์ ์ธ ์ฝ๋๊ฐ ๋ ๊ฒ์ ๋๋ค.
์์กด์ฑ ๋ฐฐ์ด
name์ด ์ ๋ฐ์ดํธ๋ ๋๋ ์คํ์ ํ์ง ์๊ณ , count๊ฐ ์ ๋ฐ์ดํธ๋ ๋๋ง ์คํ์ ํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํ ๊น์?
๋ ๋ฒ์งธ ์ธ์๋ก [count] ๋ฐฐ์ด์ ๋๊ฒจ์ฃผ๋ฉด ๋ฉ๋๋ค. ์ด ๋ฐฐ์ด์ ์์กด์ฑ ๋ฐฐ์ด(Dependency Array)์ด๋ผ๊ณ ํฉ๋๋ค. ์์กด์ฑ ๋ฐฐ์ด์ ์ถ๊ฐํ๋ฉด useEffect๊ฐ ์ฒ์ ํ๋ฉด์ ๋ ๋๋ง๋ ๋์, ์นด์ดํธ๋ผ๋ ๊ฐ์ด ๋ณํ ๋๋ง ๋ถ๋ฆฌ๊ฒ ๋ฉ๋๋ค.
useEffect ์ฝ๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํด๋ณด๊ฒ ์ต๋๋ค.
useEffect(() => {
console.log("๐ count ๋ณํ");
}, [count]);
๋ ๋๋ง๋ ๋๋ง๋ค | ๋ง์ดํธ๋ ๋๋ง | ๋ง์ดํ + value ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค
์ด๋ ๊ฒ name์ด ๋ณ๊ฒฝ๋์์ ๋๋ ์ฝ์์ ๋ฉ์ธ์ง๊ฐ ์ถ๋ ฅ๋์ง ์๊ณ , ๋งจ ์ฒ์ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋์, ์นด์ดํธ๊ฐ ์ ๋ฐ์ดํธ๋ ๋๋ง ์ถ๋ ฅ๋๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ๋ฐ๋๋ก ์์กด์ฑ ๋ฐฐ์ด์ name ๊ฐ์ ๋ฃ๋๋ค๋ฉด name์ด ์ ๋ฐ์ดํธ๋ ๋๋ง ์คํ๋ฉ๋๋ค.
// ๋ ๋๋ง๋ง๋ค ๋งค๋ฒ ์คํ
useEffect(() => {
console.log("๐ค ๋ ๋๋ง");
});
// ๋ง์ดํ
+ count ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์คํ
useEffect(() => {
console.log("๐ count ๋ณํ");
}, [count]);
// ๋ง์ดํ
+ name ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์คํ
useEffect(() => {
console.log("๐ฉท name ๋ณํ");
}, [name]);
์ถ๊ฐ๋ก, ๋ง์ดํธ๋ ๋๋ง ์คํ์ํค๊ณ ์ถ๋ค๋ฉด ๋น ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด ๋ฉ๋๋ค.
// ๋น ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด ๋ง์ดํธ๋ ๋๋ง ์คํ
useEffect(() => {
console.log("๐ ๋ง์ดํ
");
}, []);
๐งน Clean up (์ ๋ฆฌ ์์ ): ํ์ด๋จธ ์ค์ต
์ด์ ์ ๋ฆฌ ์์ ์ ์ค์ตํด๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ Toggle Timer๋ผ๋ ๋ฒํผ์ ๋ง๋ค๊ณ , ๊ทธ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ์ด๋จธ๋ฅผ ์์ํ๋ค๋ ๋ฉ์ธ์ง๋ฅผ ๋ณด์ฌ์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
const App = () => {
const [showTimer, setShowTimer] = useState(false);
return (
<div>
{showTimer && <Timer />}
<br></br>
<button onClick={() => setShowTimer(!showTimer)}>Toggle Timer</button>
</div>
);
};
export default App;
ํ์ด๋จธ๋ฅผ ์์ํ๋ค๋ ๋ฉ์ธ์ง์ ํจ๊ป ์ฝ์์ ํ์ด๋จธ๋ฅผ ์คํํ๋ค๊ณ ์ถ๋ ฅํ๋ ์ปดํฌ๋ํธ Timer์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
const Timer = (props) => {
useEffect(() => {
const timer = setInterval(() => {
console.log("ํ์ด๋จธ ์คํ ์ค...");
}, 1000);
}, []);
return (
<div>
<span>ํ์ด๋จธ๋ฅผ ์์ํฉ๋๋ค. ์ฝ์์ ๋ณด์ธ์!</span>
</div>
);
};
export default Timer;
์ฝ์์ 1์ด๋ง๋ค "ํ์ด๋จธ ์คํ ์ค..."์ด๋ผ๋ ๋ฉ์ธ์ง๊ฐ ์ฐํ๋๋ค. ๊ทธ๋ฐ๋ฐ, ์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด Toggle Timer ๋ฒํผ์ ํ ๋ฒ ๋ ๋๋ฌ ํ์ด๋จธ ์ปดํฌ๋ํธ๋ฅผ ์ ๋ณด์ด๊ฒ ๋ง๋ค์ด๋ ์ฝ์์๋ ์ฌ์ ํ 1์ด๋ง๋ค "ํ์ด๋จธ ์คํ์ค" ๋ฉ์ธ์ง๊ฐ ๋ณด์ ๋๋ค. ์ด๋ ์ ๋ฆฌ ์์ ์ ํ์ง ์์์ ๋ฐ์ํ๋๋ฐ, ์ ๋ฆฌ๋ฅผ ํ๊ธฐ ์ํด์๋ useEffect ๋ฆฌํด๊ฐ์ผ๋ก ํจ์๋ฅผ ๋ฃ์ผ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ํจ์ ์์์ ์ ๋ฆฌ ์์ ์ ํ๋ฉด ๋ฉ๋๋ค.
๋ฆฌํด๊ฐ์ ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋ ์คํ๋๋ค๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค.
useEffect(() => {
const timer = setInterval(() => {
console.log("ํ์ด๋จธ ์คํ ์ค...");
}, 1000);
return () => {
// ์ ๋ฆฌ ์์
, ์ฆ ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋ ์คํ
clearInterval(timer);
console.log("ํ์ด๋จธ๊ฐ ์ข
๋ฃ๋์์ต๋๋ค.");
};
}, []); // ๋น ๋ฐฐ์ด์ ์ ๋ฌํ์ฌ ๋ง์ดํธ๋ ๋๋ง ์คํ
์ด์ ๋ฒํผ์ ๋๋ฅด๋ฉด ํ์ด๋จธ ์คํ ์ค ๋ฉ์ธ์ง๊ฐ ์ถ๋ ฅ๋๊ณ ํ ๋ฒ ๋ ๋๋ฌ ํ์ด๋จธ๋ฅผ ๋๋ฉด ์ข ๋ฃ๋์๋ค๋ ๋ฉ์ธ์ง๊ฐ ์ ์์ ์ผ๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์ฐธ๊ณ ์๋ฃ
https://www.youtube.com/watch?v=kyodvzc5GHU&list=PLZ5oZ2KmQEYjwhSxjB_74PoU6pmFzgVMO&index=2
https://rinae.dev/posts/a-complete-guide-to-useeffect-ko/
[๋ฒ์ญ] useEffect ์๋ฒฝ ๊ฐ์ด๋
Dan Abramov์ 'A Complete Guide to useEffect' ๋ฒ์ญ
rinae.dev
'React.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React] ๋ฆฌ์กํธ Hooks (3) - useRef: DOM ์์ ์ ๊ทผ (0) | 2024.06.27 |
---|---|
[React] ๋ฆฌ์กํธ Hooks (3) - useRef: ๋ณ์ ๊ด๋ฆฌ (0) | 2024.06.26 |
[React] ๋ฆฌ์กํธ Hooks (1) - useState (0) | 2024.06.02 |