React는 상태(props, state)가 변경될 때 컴포넌트를 re-render 한다.
useState
로 내부 상태(state)를 설정하고, 상태가 변경 될 때는 컴포넌트 함수 전체를 다시 호출하게 된다.
라고 useState 게시글에서 말했는데, 이것은 다양한 Side Effect를 가진다.
예를 들어 컴포넌트가 렌더링 될 때 데이터 가져오기
, document의 타이틀 변경하기
, 구독 설정하기
를 실행하는 기능이 있다고 가정하자.
그렇다면 해당 컴포넌트의 상태(props나 state)가 변경될 때마다 컴포넌트 함수가 호출되고, 위의 기능들이 다시 실행될 것이다.
카운터 버튼 하나 클릭했을 뿐인데 fetch로 서버에 파일을 요청하고 받아오고 json으로 변환하고.. 이런 네트워크 요청이 반복된다면? 굉장히 비효율적인 프로그램이 될 것이다.
useEffect
는 기본적으로 컴포넌트 렌더링과 동일하게, DOM이 업데이트 될 때마다 특정 함수를 실행할 수 있다.
그리고 세부적으로 컴포넌트가 마운트 됐을 때 (처음 렌더링 될 때), 언마운트 됐을 때 (사라질 때), 특정 상태가 업데이트 될 때 작업을 처리할 수 있게 해주는 React Hook이다.
아래 코드는 Click me 버튼을 클릭할 때 마다 count
가 업데이트 되고, useEffect
내부의 콜백함수가 실행되며 document.title
또한 업데이트 된다.
import React, { useState, useEffect } from 'react';
export default function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
// 브라우저 API를 이용하여 문서 타이틀을 업데이트합니다.
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
useEffect
함수의 두번째 인자에는 의존값 deps
배열을 전달할 수 있다.
빈 배열 []
을 넘겨주면, 컴포넌트가 처음 렌더링 될 때만 콜백함수가 실행된다.
useEffect(() => {
// 브라우저 API를 이용하여 문서 타이틀을 업데이트합니다.
document.title = `You clicked ${count} times`;
}, []);
useEffect
콜백함수의 return 값으로 또다른 콜백함수를 전달하면, 컴포넌트가 화면에서 사라질 때마다 콜백함수(cleanup
함수)가 실행된다.
** 처음 렌더링 될 때도 해당 cleanup
함수가 실행된다.
useEffect(() => {
// 브라우저 API를 이용하여 문서 타이틀을 업데이트합니다.
document.title = `You clicked ${count} times`;
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
useEffect
함수에 의존값을 설정하려면, 두번째 인자인 deps
배열에 변수를 추가해주면 된다.
useEffect
안에서 사용하는 props나 state가 있다면 deps
에 꼭 넣어주어야 한다.
그렇지 않으면 콜백함수가 실행될 때 최신 props와 state를 가리키지 않게 된다.
useEffect(() => {
// 브라우저 API를 이용하여 문서 타이틀을 업데이트합니다.
document.title = `You clicked ${count} times`;
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, [count]);
일반적으로 마운트, 언마운트 시 하는 작업들은 다음과 같다.
props
로 받은 값을 컴포넌트의 로컬 상태로 설정