useEffect는 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 할 수 있는 React Hook이다.
컴포넌트의 최상의 레벨에서 useEffect를 호출하여 Effect를 선언한다.
import { useEffect } from 'react';
setup 함수는 optional dependencies에 무엇이 오든 컴포넌트가 DOM에 마운트되면 일단 실행된다.
setup 함수는 선택적으로 클린업 함수를 반환할 수도 있다.
useEffect는 훅이므로 컴포넌트 최상위 레벨 또는 자체 훅에서만 호출할 수 있다.
반복문이나 조건문 내부에서는 호출할 수 없다. ( 필요한 경우 새 컴포넌트 추출 후 state를 그 안으로... )
외부 시스템과 동기화하려는 목적이 아니라면 Effect가 필요하지 않을지도 모른다.
Strict 모드가 켜져 있으면 React는 첫 번째 실제 셋업 전에 개발 전용의 셋업 + 클린업 사이클을 한번 더 실행한다.
이는 클린업 로직이 셋업 로직을 "미러링"하고 setup이 수행 중인 모든 작업을 중지하거나 취소하는지를 확인하는 스트레스 테스트이다. ( 문제가 발생하면 클린업 기능을 구현해야 한다. )
의존성 중 일부가 컴포넌트 내부에 정의된 객체 또는 함수인 경우 Effect가 필요 이상으로 자주 다시 실행될 위험이 있다.
이를 해결하려면 불필요한 객체 및 함수 의존성을 제거해야 한다.
외부 시스템 연결하기
컴포넌트가 페이지에 표시되는 동안 네트워크, 일부 브라우저 API 또는 타사 라이브러리에 연결 상태를 유지해야 할 수 있다. ( 이러한 시스템은 React에서 제어되지 않으므로 외부(external)이라고 한다. )
컴포넌트를 외부 시스템에 연결하려면 컴포넌트의 최상위 레벨에서 useEffect를 호출한다.
import { useEffect } from 'react';
import { createConnection } from './chat.js';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}
1. useEffect에는 두 개의 인자를 전달해야 한다.
2. React는 필요할 때마다 setup 및 cleanup 함수를 호출하는데,이는 여러 번 발생할 수 있다.
3. 컴포넌트가 페이지에서 제거(마운트 해제)되면 마지막으로 한 번 cleanup 코드를 실행한다.
커스텀 훅으로 Effect 감싸기
Effect는 "탈출구"이다. 또는 더 나은 빌트인 솔루션이 없을 때 사용한다.
Effect를 수동으로 작성해야 하는 경우가 자주 발생한다면 이는 컴포넌트가 의존하는 일반적인
동작에 대한 custom hook을 추출해야 한다는 신호일 수 있다.
예를 들어, 이 useChatRoom 커스텀 훅은 Effect의 로직을 보다 선언적인 API 뒤에 숨긴다.
그러면 모든 컴포넌트에서 이와 같이 사용할 수 있다.
function useChatRoom({ serverUrl, roomId }) {
useEffect(() => {
const options = {
serverUrl: serverUrl,
roomId: roomId
};
const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [roomId, serverUrl]);
}
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useChatRoom({
roomId: roomId,
serverUrl: serverUrl
});
// ...