React 컴포넌트 안에서 데이터를 가져오거나 구독하고, DOM을 직접 조작하는 모든 동작을 'side effects'
라고 한다.
왜냐하면, 이것은 다른 컴포넌트에 영향을 줄 수 있고, 렌더링 과정에서는 구현할 수 없는 작업이기 때문이다.
순수 함수는 예측 가능하고, 신뢰할 수 있고, 테스트하기 쉽다.
반대로 함수 내의 구현 내용이 함수 외부에 영향을 끼치는 경우, 해당 함수는 side effect
가 있다고 얘기한다.
여기서 side effect를 일으키는 함수를 예를 들어보면, Math.random()
처럼 값이 랜덤으로 바뀌는 등 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우에 side effect를 일으킨다고 볼 수 있다.
반면, side effect를 일으키지 않는 순수 함수의 경우엔 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수이다.
useEffect
는 React 컴포넌트의 이러한 side effect들을 처리하는 방법을 제공하기 위해 존재한다.
컴포넌트 안에서 직접 side effect를 수행하는 경우, 컴포넌트의 렌더링에 방해가 된다.
side effect는 렌더링 과정과 분리되어야 한다.
side effect를 수행해야 하는 경우, 컴포넌트의 렌더링이 끝난 후에 수행되어야 한다.
바로 이 기능을 useEffect
가 제공한다.
useEffect
는 두 개의 인자를 전달한다. (함수, 배열)
import {useEffect} from 'react';
function User({name}) {
useEffect(() => {
document.title = name;
}, [name]);
return <h1>{name}</h1>;
}
첫 번째 인수로 전달하는 함수는 콜백 함수
이다.
이 함수는 컴포넌트가 렌더링 된 이후에 호출된다.
두 번째 인수는 종속성 배열이다.
이 배열은 side effect가 의존하는 모든 값을 포함해야 한다.
위의 예에서는 외부 범위의 값인 name
을 기반으로 제목을 변경하고 있으므로, name
을 종속성 배열에 포함해야 한다.
useEffect
에 종속성 배열을 전혀 제공하지 않고 함수만 제공하는 경우이 경우 함수는 컴포넌트가 렌더링 될 때마다 렌더링 이후 실행된다.
useEffect
는 종속성 배열이 없을 때 모든 단일 렌더링 후에 실행되므로, 무한 루프가 발생한다.
때로는 side effect를 멈춰야 한다.
예를 들어 setInterval
함수를 사용하는 카운트다운 타이머가 있는 경우 clearInterval
함수를 사용하지 않으면 해당 interval
은 멈추지 않는다.
또 다른 예는, WebSocket과 함께 구독을 사용하는 것이다.
구독은 더 이상 사용하지 않을 때 꺼야 하며, 이것이 바로 cleanup function이 존재하는 이유이다.
setInterval
을 사용하여 state
를 설정하고, 그 side effect를 cleaup 하지 않으면, 컴포넌트가 언마운트되고 더 이상 사용하지 않을 때 state는 컴포넌트와 함께 소멸되지만, setInterval
함수는 계속 실행된다.
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
setInterval(() => setTime(1), 1000);
// counts up 1 every second
// we need to stop using setInterval when component unmounts
}, []);
}
컴포넌트가 사라지는 경우 문제는 setInterval
이 더 이상 존재하지 않는 state
를 업데이트하려고 시도한다는 것이다.
이것은 메모리 누수
라는 오류이다.
cleanup function을 사용하려면 useEffect
함수 내에서 함수를 반환해야 한다.
이 함수 내에서 cleanup을 수행할 수 있다.
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
let interval = setInterval(() => setTime(1), 1000);
return () => {
// setInterval cleared when component unmounts
clearInterval(interval);
}
}, []);
}
컴포넌트가 언마운트될 때 cleanup function이 호출된다.
언마운트되는 컴포넌트의 일반적인 예는, 컴포넌트가 더 이상 렌더링되지 않는 애플리케이션의 새 페이지 또는 새 경로로 이동하는 것이다.