렌더링 이후 Side Effect를 수행할 수 있게 해 줍니다.
여기서 Side Effect는 무엇일까요?
첫 번째 문장의 맥락에서는 Side Effect를 부작용으로 해석하고 두 번째 문장에서는 부수적인 효과로 해석하고 있습니다. 하지만 Effect 함수(useEffect 첫 번째 인자인 함수) 내부에서 외부의 입력을 받거나 외부의 출력에 영향을 줄 수 있다는 의미에서 비슷한 의미로 볼 수 있지 않을까 생각하고 있습니다.
컴포넌트가 다시 호출이 되더라도 단 한 번만 수행해야 하는 함수가 있는 경우
어떤 변수가 변경되었을 때에만 동작을 수행하게끔 하고 싶은 경우
effect 함수에서 state를 변경하면 무한루프에 빠지게 됩니다.
function InfiniteLoop() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1); //무한루프 발생
});
return (
<div>
<button onClick={() => setCount(count + 1)}>{count}</button>
</div>
);
};
특정 변수의 값이 변경될 때만 effect를 수행하고 싶다면 두 번째 인자에 해당 변수를 넘기면 됩니다.
function EffectOnCountUp() {
const [count, setCount] = useState(0);
useEffect(() => {}, [count]); //count가 변경되었을때에만 useEffect 실행
return (
<div>
<button onClick={() => setCount(count + 1)}>{count}</button>
</div>
);
};
이 useEffect가 초기에만 필요하고 다시는 필요하지 않다면 아래와 같이 빈 배열을 사용하면 됩니다.
useEffect(() => {
setCount(count + 1);
}, []);
내가 만든 어떤 컴포넌트를 벗어날 때 실행해야 하는 동작이 있다면 return에 추가하면 됩니다.
아래 코드에서 clearInterval 하지 않으면 각각의 렌더링된 컴포넌트에서 setInterval이 살아 있는 걸 확인할 수 있습니다.
function IntervalCounter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, [count]);
return (
<>
<h1>{count}</h1>
</>
);
}