[React Hooks] useEffect
이번 글은 'Reack Hooks in Action'의 'Chapter 4. Working with side effects'의 내용을 요약 정리한 것입니다.
들어가며
- 컴포넌트 내에 일어나는 부수 효과(side effects)에 대해 알아본다.
- useEffect Hook으로 부수 효과를 감싼다.
- 종속성 목록(dependency list)를 명시함으로써 effect가 실행되는 경우를 통제한다.
- effect에서 cleanup 함수를 반환한다.
- 컴포넌트에 쓰이는 fetch 데이터에 effect를 활용한다.
부수 효과가 발생하는 경우들
- 페이지 제목을 강제로 설정
- setInterval, setTimeout 등 timer 함수로 작업
- DOM 내 요소의 너비, 높이, 위치 등을 측정
- console. 혹은 다른 서비스에 메시지를 기록
- local storage의 값을 불러오거나 설정할 떄
- data를 불러오거나(fetching) 서비스 구독 혹은 취소할 때
예제와 함께 useEffect 알아보기
- 렌더링될 때마다 부수 효과가 일어나는 경우
- 컴포넌트가 마운트될 때 한 번만 부수 효과가 일어나는 경우
- 함수를 반환하여 부수 효과를 정리하는(cleaning up) 경우
- 종속성을 정의하여 effect 실행을 제어하는 경우
1. 렌더링될 때마다 부수 효과가 일어나는 경우
위와 같이 두 번째 인자 없이 useEffect Hook을 쓰면 React는 useEffect 내 effect 함수를 렌더링이 일어나고 난 뒤마다 실행한다.
2. 컴포넌트가 마운트될 때 한 번만 부수 효과가 일어나는 경우
useEffect의 두 번째 인자는 종속성 목록이다. React는 컴포넌트가 effect 함수를 마지막으로 호출한 시점과 비교했을 때 목록 안의 값들이 바뀌었는지 확인하여 effect를 실행할지를 결정한다. 종속성 목록을 빈 배열로 두면 바뀔 값이 없으므로 컴포넌트가 처음 마운트될 때 한 번만 effect 함수가 실행된다.
3. 함수를 반환하여 부수 효과를 정리하는(cleaning up) 경우
React는 컴포넌트가 언마운트될 때 클린업 함수를 실행한다. 하지만 이 경우에만 실행하는 것은 아니다. 컴포넌트가 리렌더링될 때마다 React는 effect 함수가 다시 실행된다면 effect 함수가 실행되기 전에 클린업 함수를 호출한다. 여러 effect 함수가 반복해서 실행되는 경우 React는 이 effect 함수에 대한 모든 클린업 함수를 호출한다. 클린업 작업이 끝나면 React는 필요한 만큼 effect 함수를 반환한다.
4. 종속성을 정의하여 effect 실행을 제어하는 경우
React는 컴포넌트를 호출할 때마다 useEffect에 대한 호출에 쓰이는 종속성 목록 내 값의 기록을 유지한다. 마지막 호출과 비교하여 배열 내 값이 바뀌었을 경우 React는 effect 함수를 실행한다. 바뀐 값이 없다면 effect 함수를 실행하지 않는다.
중간 요약
요약
- 때때로 컴포넌트는 주로 브라우저에서 React 데이터 흐름의 밖에 접속하거나 다른 API들과 직접적으로 상호작용을 한다. 이때 부수 효과(side effect)가 발생하므로 useEffect로써 처리해줘야 한다.
- 일반적인 부수 효과로는 페이지 타이틀 강제 변경, setInterval이나 setTimeout과 같은 timer 메서드, DOM 요소의 너비, 높이, 위치 측정, console에 메시지 기록, local storage에 값 읽고 쓰기, 데이터 가져오기 및 서비스 구독/구독 취소 등이 있다.
- useEffect Hook의 첫 번째 인자로 effect 함수 안에 부수 효과를 넣어 전달한다. 아래 코드의 경우 React는 렌더가 끝날 때마다 effect 함수를 실행한다.
- effect 함수가 실행될 때 관리하기 위해서 useEffect Hook의 두 번째 인자로 종속성 배열을 전달한다.
- 컴포넌트가 마운트 될 때 React가 effect 함수를 한 번만 실행시키기 위해 빈 종속성 배열을 전달한다.
- 명시된 종속성 값들이 변화할 때마다 React가 effect 함수를 실행시키게 하기 위해서 effect 함수의 종속성을 종속성 배열 안에 전달한다.
- React는 effect 함수를 재실행하기 전과 컴포넌트가 언마운트될 때 클린업 함수를 effect 함수에서 반환한다.
- fetch-on-render 어프로치를 쓰는 경우 effect 함수 안의 데이터를 불러온다. React는 컴포넌트를 렌더링하고 data-fetching 코드를 실행한다. 데이터가 도착했을 때 컴포넌트가 리렌더링된다.
- 경쟁 조건(race conditions)을 피하고 아무 것도 반환하지 않거나 효과 함수에서 정리 함수를 반환하는 규칙을 따르려면 effect 함수 안에 async 함수를 적는다. 이 함수는 필요한 만큼 호출할 수 있다.
- useEffect에 대한 호출 안에 부수 효과를 개별적으로 넣는다. 이렇게 하면 각 effect 함수가 무엇인지 알기 쉽고 별도의 종속성 목록을 사용하여 효과가 실행되는 시기를 더 쉽게 제어할 수 있습니다. 또한 effect 함수를 사용자 정의 Hooks로 추출하기 쉽다.
- 리렌더링될 때 여러 effect가 실행될 경우 React는 effect 함수 자체를 실행하기 전에 재실행 effect 함수에 대한 모든 클린업 함수를 호출합니다.