일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- context.api
- radixui
- 합성 컴포넌트
- 프론트엔드
- provider 패턴
- 오블완
- sharedworker
- 티스토리챌린지
- 회고
- JavaScript
- 이것저것
- MicroFrontEnd
- CRA
- 에세이
- react
- 리액트
- 웹워커
- CustomHook
- vite
- Web
- frontend
- TypeScript
- server component
- virtaullist
- 아키텍처
- 클린코드
- Webworker
- 자바스크립트
- MFA
- 리팩토링
- Today
- Total
Lighthouse of FE biginner
[클린코드 리액트] useEffect 바르게 사용하기 본문
useEffect 훅은 리액트에서 부수 효과를 일으키는 훅으로 여러개의 컴포넌트 생명주기를 다룰수 있는 훅 입니다. 그만큼 많이 사용하고 자주 사용하는 훅이지만 잘못 사용하면 무한 루프가 발생하던지 예상치 못한 버그가 발생할 수 있습니다.
가끔 개발된 컴포넌트를 보다보면 하나의 useEffect 훅에 여러 역할을 하는 함수를 넣는 경우가 있습니다. 이는 정말 좋지 못한 케이스이며 부수 효과로 인해 불필요한 로직이 실행됩니다.
function App() {
const [isSuccess, setIsSuccess] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(() => {
const fetch = async () => {
const res = fetch("url")
.then((res) => {
setIsError(false);
setIsSuccess(true);
return res.json();
})
.catch(() => {
setIsError(true);
setIsSuccess(false);
});
return res;
};
fetch();
if (isSuccess) {
// ~~~
}
if (isError) {
// ~~
}
}, [isError, isSuccess]);
return (
...
);
}
위 코드는 극단적 예시입니다. 사실 실제로는 이런식으로 코드를 작성하는 케이스는 없을 것 입니다. 위 예시 코드에서는 하나의 useEffect 함수에서 데이터 패칭과 성공, 실패 케이스에 따른 분기 처리까지 함께 처리하고 있습니다. 위 케이스의 경우 promise가 resolve되기 이전에 성공, 실패 분기 처리를 함으로써 결과값을 예측하기 어려워집니다. 또한 의존성 배열에 promise가 resolve될 때 변경해주는 플래그 값을 넣어줬기 때문에 무한루프가 발생할 위험이 있습니다.
이 경우 해당 훅의 함수를 아래와 같이 분리할 수 있습니다.
function App() {
const [isSuccess, setIsSuccess] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(() => {
const fetch = async () => {
const res = fetch("url")
.then((res) => {
setIsError(false);
setIsSuccess(true);
return res.json();
})
.catch(() => {
setIsError(true);
setIsSuccess(false);
});
return res;
};
fetch();
}, []);
useEffect(() => {
if (isSuccess) {
// ~~~
}
if (isError) {
// ~~
}
}, [isSuccess, isError]);
return (
...
);
}
useEffect 훅의 로직을 분리해 각 함수가 한 가지의 역할만 하도록 분리했습니다. 이럴 경우 코드의 가독성이 좋아지고 SOLID 원칙 중 SRP(단일 책임의 원칙)을 지킬 수 있게 됩니다. 또한 데이터를 패칭하는 훅에서 불필요한 의존성을 제거함을써 불필요한 부수효과를 방지할 수 있게됩니다.
만약 useEffect 함수의 역할을 코드상 눈에 띄게 드러내기 어렵다면 기명 함수를 활용할 수 있습니다.
useEffect(function getData() {
const fetch = async () => {
const res = fetch("url")
.then((res) => {
setIsError(false);
setIsSuccess(true);
return res.json();
})
.catch(() => {
setIsError(true);
setIsSuccess(false);
});
return res;
};
fetch();
}, []);
useEffect 훅 내부 함수에 화살표 함수를 넣어주는 것이 아닌 표현식을 활용한 함수를 넣어줬습니다. 이렇게 간단한 방법으로 해당 훅의 역할을 명확하게 표현할 수 있습니다.
'[WEB] 프론트엔드' 카테고리의 다른 글
Eject된 CRA 프로젝트에서 Vite 프로젝트로 마이그레이션 하기 (0) | 2024.07.02 |
---|---|
[React] 컴포넌트 설계하기 (0) | 2024.06.30 |
[클린코드 리액트] 컴포넌트 내부에 컴포넌트 선언 지양하기 (0) | 2024.06.10 |
[클린코드 리액트] Props로 Object 내리는 것 지양하기 (1) | 2024.06.09 |
[클린코드 리액트] Css in JS 인라인 스타일 지양하기 (0) | 2024.06.09 |