useQuery는 데이터 요청 상태를 나타내는 여러 값을 제공한다.
아래 예제처럼 요청 상태에 따라 별도 동작을 시킬 수 있고, 템플릿에 사용해 요청 상태에 따른 화면을 표시할 수 있다.
상태 값 | 설명 |
---|---|
isLoading | 데이터 요청 중 (첫 요청) |
isFetching | 백그라운드에서 데이터 가져오는 중 |
isError | 요청 실패했을 때 true |
error | 에러 객체 (에러 메시지 포함) |
isSuccess | 데이터가 정상적으로 로드됨 |
const { data, isLoading, isFetching, isError, error } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
});
if(isLoading) console.log('데이터 로딩 중...');
if(isFetching) console.log('새로운 데이터를 가져오는 중...');
if(isError) console.error('에러 발생:', error);
onError와 retry로 API 요청이 실패했을 때 에러를 처리할 수 있다.
onError
const { data } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
onError: (error) => {
console.error('에러 발생:', error);
},
});
retry
네트워크 오류 등으로 요청이 실패했을 때 자동으로 재요청한다.
const { data } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
retry: 3, // 최대 3번 재시도
retryDelay: 3000, // 실패 시 3초 후 재시도
});
데이터 로드 전까지 초기 데이터를 표시할 수 있다.
initialData
쿼리의 초기 데이터를 설정한다.
const { data, isLoading } = useQuery({
queryKey: ['userProfile'],
queryFn: fetchUserProfile, // 사용자 프로필 API 호출
initialData: {name: '알 수 없음', age: 0},
staleTime: 1000 * 60 * 5, // 5분 동안 데이터를 fresh 상태로 유지
});
placeholderData
쿼리의 임시 데이터를 설정한다.
const { data, isLoading } = useQuery({
queryKey: ['posts', page], // 현재 페이지 번호
queryFn: () => fetchPosts(page), // 페이지별 게시글 불러오기
placeholderData: { id: 0, title: '로딩 중...', content: '게시글을 불러오는 중입니다.'}
});
둘다 로딩 중에 보일 데이터를 설정하는 건 비슷하지만 캐싱 차이가 있다.
initialData는 값이 캐싱되고, placeholderData는 캐싱되지 않는다.
그래서 staleTime이 0이면 initialData도 placeholderData처럼 동작하는 것처럼 보인다.
initialData
staleTime 동안 새 데이터를 불러오지 않고 initialData를 사용한다.
이후 staleTime이 지나 새 데이터를 받으면 새 데이터가 캐싱된다.
gcTime이 지나면 캐시가 삭제되기 때문에, 다시 initialData를 캐싱한다.
placeholderData
캐싱되지 않기 때문에 staleTime과 관계없이 새 데이터를 불러온다.
캐시 데이터가 없는 상태에서 로딩중일 때만 보여진다.
정리
초기값이 “진짜 데이터”여야 하고, 캐싱이 필요하다면 → initialData
초기값이 “임시 데이터”여도 되고, 캐싱이 필요 없다면 → placeholderData
브라우저 새로고침 시 설정한 placeholderData가 계속 나와서 찾아봤는데, 탄스택 쿼리는 새로고침을 하면 캐시와 stale상태의 데이터가 초기화된다고 한다. 새로고침을 해도 캐시가 남아서 캐시가 없는 처음에만 placeholderData가 보일 거라 생각했다.