-
[WizSched] QueryErrorResetBoundary 적용, 에러 처리Front-End/Project 2024. 4. 2. 22:46
🍀 목차
설계
QueryErrorResetBoundary?
구현설계
개발하며 마주친 401, 403 등의 에러들을 어떻게 처리할지 고민했다. 사용자 입장에서 어떤 에러가 발생했는지 알 수 있게 최대한 상수화해 보자는 생각이 들었다.
작성은 Google Calendar 가이드 API 오류 처리 항목을 참고했다. 401, 403 에러인 경우 재로그인을 해야 하므로
redirect
변수를 true로 주었다.const ERRORS: ErrorMap = { 400: { message: '잘못된 요청입니다.💦', redirectState: { redirect: false, }, }, 401: { message: '잘못된 인증 정보입니다. 재로그인 해주세요.💦', redirectState: { redirect: true, path: RoutePath.LOGIN, }, }, // ... 0: { message: '예상치 못한 오류가 발생했습니다. 계속해서 같은 문제 발생 시, 개발자에게 문의해주세요.🐛', redirectState: { redirect: false, }, }, } as const;
그 외 예상치 못한 오류는 key값 0으로 매치시켰다.
QueryErrorResetBoundary?
TanStack Query의
QueryErrorResetBoundary
는 쿼리에 suspense를 사용하는 경우 오류 발생 후 렌더링 시 쿼리를 다시 시도할 수 있다. 사용법은 아래와 같다.import { QueryErrorResetBoundary } from '@tanstack/react-query' import { ErrorBoundary } from 'react-error-boundary' const App: React.FC = () => ( <QueryErrorResetBoundary> {({ reset }) => ( <ErrorBoundary onReset={reset} fallbackRender={({ resetErrorBoundary }) => ( <div> There was an error! <Button onClick={() => resetErrorBoundary()}>Try again</Button> </div> )} > <Page /> </ErrorBoundary> )} </QueryErrorResetBoundary> )
ErrorFallback
컴포넌트가 있기 때문에 위 예시코드의fallbackRender
프로퍼티를FallbackComponent
로 바꿔주었다.구현
기존
CalendarSelector
에 QueryErrorResetBoundary를 적용시킨다.import { QueryErrorResetBoundary } from '@tanstack/react-query'; import { Suspense } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import ErrorFallback from '@/components/fallback/ErrorFallback'; import LoadingFallback from '@/components/fallback/LoadingFallback'; // ... const CalendarSelector = () => { return ( <div className="py-4"> <QueryErrorResetBoundary> {({ reset }) => ( <ErrorBoundary onReset={reset} FallbackComponent={ErrorFallback}> <Suspense fallback={<LoadingFallback />}> <CalendarDropDown /> </Suspense> </ErrorBoundary> )} </QueryErrorResetBoundary> </div> ); }; export default CalendarSelector;
에러 텍스트만 띄우던 ErrorFallback도 개선한다.
props로 전달받은
error
를 만들어둔 에러 상수 객체와 연결,resetErrorBoundary
를 재시도 버튼 클릭 시 onClick 이벤트로 연결해 준다.import { FallbackProps } from 'react-error-boundary'; import { useNavigate } from 'react-router-dom'; import Button from '@/components/button/Button'; import ERRORS from '@/constants/errors'; import useSupabaseAuth from '@/hooks/useSupabaseAuth'; const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => { const navigate = useNavigate(); const { logOutWithGoogle } = useSupabaseAuth(); const statusCode = error.response.status || 0; const errorMessage = ERRORS[statusCode].message; const redirectState = ERRORS[statusCode].redirectState; const handleLogoutAndRedirect = (path: string) => { logOutWithGoogle(); navigate(`/${path}`); }; return ( <> <p>{errorMessage}</p> {redirectState.redirect ? ( <Button variant="contained" color="secondary" onClick={() => handleLogoutAndRedirect(redirectState.path)} > 페이지 이동 </Button> ) : ( <Button variant="contained" color="error" onClick={resetErrorBoundary}> 재시도 </Button> )} </> ); }; export default ErrorFallback;
const handleLogoutAndRedirect = (path: string) => { logOutWithGoogle(); navigate(`/${path}`); };
재로그인이 필요한 경우는 버튼 클릭 시에 로그아웃 후 로그인 페이지로 이동시켰다.
문서에서는 데이터에 대한 응답일 경우
redirect
사용을 권장하지만, 해당되지 않는다고 생각하여useNavigate
hook을 사용하였다. 함수 이름을handleLogoutAndNavigate
로 해야 하나 했지만 상수에서 redirectState로 관리해서... Redirect를 붙이기로 결정했다.참고자료
https://developers.google.com/calendar/api/guides/errors?hl=ko
https://reactrouter.com/en/main/hooks/use-navigate
https://tanstack.com/query/latest/docs/framework/react/reference/QueryErrorResetBoundary