일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- AWS
- 클라우드
- es6
- 프론트엔드
- docker
- 웹
- 알고리즘
- CSS
- 파이썬
- 백엔드
- next.js
- 이슈
- 타입스크립트
- 가상화
- BFS
- 쿠버네티스
- k8s
- TypeScript
- kubernetes
- JavaScript
- 솔리디티
- node.js
- react
- 자바스크립트
- 백준
- 블록체인
- 컴퓨터공학
- 리액트
- 이더리움
- HTML
- Today
- Total
즐겁게, 코드
useEffect 내에서 async 함수를 사용할 때의 주의점 본문
웹 어플리케이션 특성상 로드와 동시에 서버로부터 데이터를 불러와야 하는 경우가 자주 있습니다.
아마 대부분의 경우 useEffect 또는 useLayoutEffect 훅을 활용해 렌더링이 끝난 후 데이터를 불러올 텐데요, 한번 샘플 코드를 보겠습니다.
const getGroupList = async () => {
await axios
.get(`${GROUP_ENDPOINT}?func=getAllGroup`)
.then((res) => setGroupList(res.data));
};
useEffect(getGroupList, []);
컴포넌트 렌더링을 마친 후 useEffect 훅으로 getGroupList 함수를 호출해 그룹 리스트 상태값을 초기화해주고 있습니다.
그런데 이렇게 짜면 절대로 안됩니다!!
⏱ async와 useEffect
잠깐 async 함수와 useEffect의 구조를 간단히 살펴보도록 하겠습니다.
여러 프라미스를 동기적으로 다룰 수 있게 해주는 async 함수는 명시하지 않더라도 항상 프라미스를 반환합니다.
// 이렇게 속이 완전히 빈 async 함수더라도
const getData = async () => {};
console.log(getData());
// Promise { undefined } 를 출력합니다.
useEffect는 이렇게 생겼습니다.
useEffect(
// 이펙트 함수
() => {
// 클린업 동작
return () => {
}
}, [의존값 목록])
내부의 이펙트 함수는 컴포넌트의 첫 렌더링 시와 의존값 목록의 값이 변할때 호출되며, 이펙트 함수에서 반환하는 함수는 이펙트 함수가 호출되기 전과 컴포넌트가 언마운트될때 한 번씩 호출됩니다.
자, 그럼 위에서 봤던 코드를 해석해보겠습니다.
// 1. getGroupList를 이펙트로 전달
useEffect(getGroupList, []);
// 2. 이펙트 함수의 본문
useEffect(() => {
axios.get(`${GROUP_ENDPOINT}?func=getAllGroup`)
.then((res) => setGroupList(res.data));
// async 함수 특성상 항상 프라미스를 반환함.
return new Promise();
}, []);
async 함수를 useEffect에 그대로 전달하면 구조상 프라미스를 반환할 수밖에 없고, 이펙트 함수에서는 클린업 함수를 리턴해야 하는데 리액트가 받아든건 덜렁 프라미스 하나입니다.
이로 인해 렌더링 성능에도 영향을 미칠 수 있고, 경우에 따라서는 다른 컴포넌트를 렌더링할 시 아예 오류를 출력하기도 합니다.
🛠 해결책
사실 개발자 도구의 경고를 잘 읽어보면 해결 방법이 깔끔하게 적혀있습니다.
const getGroupList = async () => {
await axios
.get(`${GROUP_ENDPOINT}?func=getAllGroup`)
.then((res) => setGroupList(res.data));
};
useEffect(() => {
getGroupList();
}, []);
바로 이렇게 이펙트를 익명 함수로 선언하고 함수 본문에서 async 함수를 호출하는 것인데요, 이러면 async 함수가 프라미스를 반환하더라도 이펙트는 아무것도 반환하지 않아 클린업으로 이상한 값을 넘길 우려가 사라집니다! 😄
'🎨 프론트엔드 > React.js' 카테고리의 다른 글
useState 똑똑하게 사용하기 (0) | 2021.05.10 |
---|---|
forwardRef로 함수 컴포넌트의 ref 전달하기 (0) | 2021.04.28 |
컴포넌트 내에서 라우팅 경로와 쿼리스트링 추출하기 (0) | 2021.04.12 |
react-redux 로 상태 관리하기 - 01. 리덕스란 (0) | 2021.04.05 |
제어 컴포넌트와 비제어 컴포넌트 (2) | 2021.04.01 |