일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 네이버 테크 콘서트
- 함수
- npm
- 레인지 슬라이더
- 인사이드 자바스크립트
- 코드스쿼드
- AWS
- 알고리즘
- 러닝 자바스크립트
- 회고의 회고
- html
- 우아한테크캠프 4기
- Hello Coding HTML5+CSS3
- 주간 회고
- 자바스크립트 객체
- 모듈 배포하기
- CSS
- 리액트
- 개인 프로젝트
- 토이 프로젝트
- 토이프로젝트
- 우아한테크코스
- 자바
- toast
- 프로그래머스
- 자바스크립트
- ES6
- express
- 우아한테크캠프
- 우아한형제들
- Today
- Total
블로그
[토스트] 리액트 useEffect: 개발자가 알아야 할 네가지 팁을 읽고 본문
리액트 useEffect: 개발자가 알아야 할 네가지 팁
React useEffect: 4 Tips Every Developer Should Know
리액트 Hook에서 useEffect 함수를 어떻게 작성하면 좋을 지에 대해 짤막한 네 개의 팁을 공유하는 포스팅이다.
1. 단일 목적의 useEffect
먼저 useEffect는 단일 목적의 함수로 분리해야 한다.
function App() {
const [varA, setVarA] = useState(0);
const [varB, setVarB] = useState(0);
// 이렇게 하면 안된다!
useEffect(() => {
const timeoutA = setTimeout(() => setVarA(varA + 1), 1000);
const timeoutB = setTimeout(() => setVarB(varB + 2), 2000);
return () => {
clearTimeout(timeoutA);
clearTimeout(timeoutB);
};
}, [varA, varB]);
return (
<span>
Var A: {varA}, Var B: {varB}
</span>
);
}
위의 코드는 한 번의 상태 변경으로 여러 상태 변수에 업데이트가 발생하게 된다.
포스팅에는 정리되어 있지 않지만 이유는 아래와 같다.
위의 코드에서 Effect Hook은 두 값 중 하나가 변경되었을 때, cleanup 함수를 호출한다.
varA와 varB의 변경은 setTimeout으로 처리되며, setTimeout의 콜백은 매크로 태스크 큐에 등록된다.
매크로 태스크 큐는 FIFO의 구조를 가지므로 먼저 큐에 추가된 timeoutA가 먼저 콜 스택으로 이동하게 된다.
이후 varA의 변화가 먼저 일어나며, Effect Hook은 cleanup 함수를 호출하게 되므로 매크로 태스크 큐에 존재하는 timeoutB는 clearTimeout 처리가 된다.
그러므로 실제 실행 시 Var A만 변경된다.
이를 방지하기 위해서는 useEffect를 분리해야 한다.
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]);
useEffect(() => {
const timeout = setTimeout(() => setVarB(varB + 2), 2000);
return () => clearTimeout(timeout);
}, [varB]);
2. 가능하다면 커스텀 훅을 사용한다
포스팅의 내용대로 커스텀 훅을 사용하게 되면 코드가 약간이나마 길어지긴 하지만 명확하게 분리된 함수를 구현할 수 있다.
3. 조건부 useEffect의 옳은 방법
특정 기준 까지만 동작해야 할 때, cleanup이 실행되도록 처리하기보다 기준을 넘어섰으면 즉시 return하는게 좋다.
실제로 큰 문제는 생기지 않지만 가독성 측면에서 매우 깔끔해보인다.
ps에서 예외처리를 최상단에 해주는 느낌?
// 나쁜 방법, 오류는 없음.
useEffect(() => {
let timeout;
if (varA < 5) {
timeout = setTimeout(() => setVarA(varA + 1), 1000);
}
// 매번 cleanup 함수가 호출
return () => clearTimeout(timeout);
}, [varA]);
// 좋은 방법
useEffect(() => {
// 기준이 넘으면 즉시 종료
if (varA >= 5) return;
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]);
4. useEffect 안에서 사용하는 모든 변수들을 디펜던시 배열에 추가한다
useEffect의 두 번째 파라미터인 디펜던시 배열에 내부 동작에서 사용하는(조회, 수정 전부) 모든 변수들을 추가해야 테스트 및 디버깅이 수월해진다고 한다.
// 잘못된 방법
function App() {
// ...
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + varB), timeCount);
return () => clearTimeout(timeout);
}, []); // 피해야한다: varA 가 디펜던시 배열에 없다.
return <span>Var A: {varA}</span>;
}
// 옳은 방법
function App() {
// ...
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + varB), timeCount);
return () => clearTimeout(timeout);
}, [varA, varB, timeCount]); // 이렇게 해야한다. 모든 디펜던시가 배열에 들어가 있다.
return <span>Var A: {varA}</span>;
}
예제 코드를 약간 수정했다.
최근 리액트를 학습하며, 각종 훅을 머릿속에 끼얹고 있는 중이다.
리액트 공식 사이트에서 별도 페이지를 할애하면서 useEffect를 다루는 것을 보고, 그만큼 중요한 녀석이 아닐까 생각해서 그런지 재미읽게 읽은 느낌이다.
'아티클' 카테고리의 다른 글
[TOAST] React.memo() 현명하게 사용하기를 읽고 (1) | 2021.04.18 |
---|---|
[TOAST] 더 나은 UX를 위한 React에서 스켈레톤 컴포넌트 만들기를 읽고 (0) | 2021.04.17 |
[우아한형제들] 팀 문화의 탄생을 읽고 (0) | 2021.04.12 |
[테크 콘서트] TECH CONCERT: FRONT END 2019 - 데이터 상태 관리. 그것을 알려주마를 보고 (0) | 2021.03.21 |
[테크 콘서트] TECH CONCERT: FRONT END 2019 - 빠르게 훑어보는 웹 개발 트렌드를 보고 (0) | 2021.03.20 |