무엇
useQueryErrorResetBoundary는 가장 가까운 QueryErrorResetBoundary 안의 쿼리 에러들을 초기화하는 reset 함수를 돌려주는 훅이다. 바운더리가 없으면 전역으로 초기화한다.
쿼리가 던진 에러를 React 에러 바운더리로 받아 처리할 때 쓴다. reset을 바운더리의 onReset에 연결해 두면, 사용자가 "다시 시도"를 눌렀을 때 실패한 쿼리들이 에러를 털고 다시 실행된다.
const { reset } = useQueryErrorResetBoundary()
무슨 일이 일어나나
쿼리에 throwOnError를 켜면(또는 useSuspenseQuery를 쓰면), 실패한 쿼리는 값을 반환하는 대신 렌더 중에 에러를 던진다. 이 에러는 가장 가까운 React 에러 바운더리가 붙잡아 폴백 UI를 보여준다.
문제는 그다음이다. 에러 바운더리는 한번 에러를 잡으면 그 상태로 굳는다. 그냥 다시 렌더한다고 쿼리가 되살아나지 않는다 — 쿼리 캐시에도 에러가 남아 있기 때문이다. reset은 이 두 가지를 함께 푼다. 캐시에 쌓인 쿼리 에러를 지우고, 바운더리가 폴백에서 정상 렌더로 돌아가도록 신호를 준다. 그래서 재시도 버튼이 실제로 데이터를 다시 불러온다.
사용법
reset을 에러 바운더리의 onReset에 넘긴다. 아래는 react-error-boundary와 함께 쓰는 표준 형태다.
import { useQueryErrorResetBoundary } from '@tanstack/react-query'
import { ErrorBoundary } from 'react-error-boundary'
function App() {
const { reset } = useQueryErrorResetBoundary()
return (
<ErrorBoundary
onReset={reset}
fallbackRender={({ resetErrorBoundary }) => (
<div>
데이터를 불러오지 못했습니다.
<button onClick={() => resetErrorBoundary()}>다시 시도</button>
</div>
)}
>
<Page />
</ErrorBoundary>
)
}
resetErrorBoundary()가 바운더리를 다시 렌더 상태로 돌리고, 그 과정에서 onReset으로 연결한 reset이 쿼리 에러를 지운다. <Page /> 안의 쿼리가 다시 실행된다.
실무 예시
Suspense로 데이터를 기다리는 화면에서, 실패 시 재시도 버튼을 보여주는 경우다. useSuspenseQuery는 로딩 중엔 서스펜스로 넘기고 실패 시엔 에러를 던지므로, 로딩과 에러 처리를 바깥 바운더리에 맡긴다.
import { Suspense } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import {
useQueryErrorResetBoundary,
useSuspenseQuery,
} from '@tanstack/react-query'
function GroupList() {
const { data } = useSuspenseQuery({
queryKey: ['groups'],
queryFn: fetchGroups,
})
return <ul>{data.map((g) => <li key={g.id}>{g.name}</li>)}</ul>
}
export function Groups() {
const { reset } = useQueryErrorResetBoundary()
return (
<ErrorBoundary
onReset={reset}
fallbackRender={({ resetErrorBoundary }) => (
<button onClick={() => resetErrorBoundary()}>다시 시도</button>
)}
>
<Suspense fallback={<p>불러오는 중…</p>}>
<GroupList />
</Suspense>
</ErrorBoundary>
)
}
왜 중요한가
이 훅은 쿼리 에러를 에러 바운더리로 던지는 방식을 쓸 때만 등장한다 — Suspense나 throwOnError를 켠 화면이다. 손에 잡은 상태(isError·error)로 에러를 화면 안에서 처리한다면 쓸 일이 없다. 하지만 로딩·에러를 컴포넌트 바깥 경계로 걷어내는 설계를 택했다면, 재시도가 실제로 동작하게 만드는 데 반드시 필요한 연결 고리다. 좁고 특정한 도구지만, 그 자리에서는 대체재가 없다.
Reference