| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- styled-components
- CSS
- 코딩테스트
- TypeScript
- 비전공자
- GIT
- 국비지원교육
- useMemo
- 개발자취업부트캠프
- 개발 공부
- 공식문서
- 프론트엔드
- 모던 딥 다이브 자바스크립트
- 알고리즘
- 패스트캠퍼스
- 프로그래머스
- 리액트
- 내일배움카드
- react
- JavaScript
- 이벤트
- 자료구조
- 입문
- Github
- MegabyteSchool
- 모던 자바스크립트 딥 다이브
- next.js
- 자바스크립트
- 메가바이트스쿨
- useRef
- Today
- Total
개발 기록 남기기✍️
[React] Custom Hook - 초기 렌더링 때 useEffect 실행 막기 본문
🤷🏻♀️ 문제 상황


React와 REST API를 활용하여 지난 과제 때 바닐라 JS로 만들었던 투두리스트를 다시 만들고 있는 중이다.
useEffect를 사용하여 todoItem의 done 속성이 바뀔 때마다 useEffect를 실행하고 API 통신을 하도록 코드를 작성했다.
근데 useEffect의 특성 상, 컴포넌트가 처음 렌더링 될 때 state가 세팅되므로 state가 변화되었다고 감지해 종속 배열에 상관없이 초기 렌더링 때 useEffect가 항상 실행된다.
그래서 초기 렌더링 떄 useEffect가 실행되고, 수정할 todoItem이 세팅되지 않은 상태이기 때문에 API 요청에 빈 데이터가 들어가게 되고, 이로 인해 Network Error가 발생하게 되었다.
💻 해결책 - useRef를 활용한 Custom hook
이 문제를 해결하기 위해 useRef를 사용해서 컴포넌트가 마운트되었는지 여부를 추적했다.
컴포넌트 최상단에 const isMounted = useRef(false)를 선언해주고, useEffect 안에서 if문을 활용하여 isMounted가 true일 때만 API 요청 함수를 실행하고, false일 때는 isMounted를 true로 변경시켜주었다.
function TodoItem({ todo }) {
...
const isMounted = useRef(false);
...
const handleChangeDone = async (todo) => {
setIsDone(!isDone);
setTodoItem({ ...todo, done: !isDone });\
};
const setPostsByResponse = async () => {
await editTodoAPI(todoItem);
const data = await getTodosAPI();
setTodoList([...data]);
};
useEffect(() => {
if(isMounted.current) {
setPostsByResponse()
} else {
isMounted.current = true;
}
}, [isDone]);
...
}
초기 렌더링 시 useEffect가 실행되면 useEffect는 isMounted의 값만 바꾸고 끝난다. 이후에 isDone의 상태가 변경될 떄마다 useEffect가 실행되고, setPostsByResponse 함수가 실행되게 된다.
이 부분을 custom hook으로 만들어서 다른 파일로 뺄 수 있을 것 같다.
// useDidMountEffect.jsx
import { useRef, useEffect } from "react";
export const useDidMountEffect = (func, deps) => {
const isMounted = useRef(false);
useEffect(() => {
if (isMounted.current) func();
else isMounted.current = true;
}, deps);
};
// 코드에 적용
import { useDidMountEffect } from '../../../utils/useDidMountEffect';
function TodoItem({ todo }) {
...
const setPostsByResponse = async () => {
await editTodoAPI(todoItem);
const data = await getTodosAPI();
setTodoList([...data]);
};
useDidMountEffect(setPostsByResponse, [isDone]);
...
}
코드가 훨씬 깔끔해진 걸 볼 수 있다.

useRef를 어떻게 사용해야할 지 감이 안 잡혔는데, 해당 hook을 만들어보니까 대충 어떻게 써야할 지 이제는 좀 알 것 같다. (진짜 대충...)
'Front-End > React' 카테고리의 다른 글
| [React] React Hooks, useState란 무엇인가 (0) | 2023.03.19 |
|---|---|
| [React] useEffect란 무엇인가 (0) | 2023.03.16 |
| [React] useReducer란 무엇인가 (0) | 2023.03.13 |
| [React] Context API란 무엇인가 (0) | 2023.03.10 |
| [React] useRef란 무엇인가 (0) | 2023.03.07 |