Skip to content

Commit

Permalink
feat: implement error boundary
Browse files Browse the repository at this point in the history
  • Loading branch information
CH4MD0M committed Feb 4, 2025
1 parent 70a41a6 commit be6dac5
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 5 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
"nanoid": "^5.0.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^5.0.0",
"react-hook-form": "^7.53.2",
"react-icons": "^5.3.0",
"react-number-format": "^5.4.2",
"react-router-dom": "^6.27.0",
"react-spinners": "^0.15.0",
"swiper": "^11.1.15",
"use-sync-external-store": "^1.2.2",
"zod": "^3.23.8",
Expand Down
25 changes: 25 additions & 0 deletions src/components/boundary/FetchBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { ReactNode } from 'react';
import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { MoonLoader } from 'react-spinners';

import DefaultErrorFallback from './FetchErrorFallback';

interface FetchBoundaryProps {
children: ReactNode;
loadingFallback?: ReactNode;
onReset?: () => void;
}

const FetchBoundary = ({
children,
loadingFallback = <MoonLoader color="#7752FE" size={40} />,
}: FetchBoundaryProps) => {
return (
<ErrorBoundary FallbackComponent={DefaultErrorFallback}>
<Suspense fallback={loadingFallback}>{children}</Suspense>
</ErrorBoundary>
);
};

export default FetchBoundary;
50 changes: 50 additions & 0 deletions src/components/boundary/FetchErrorFallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import styled from '@emotion/styled';
import { useQueryErrorResetBoundary } from '@tanstack/react-query';
import type { FallbackProps } from 'react-error-boundary';

const FetchErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => {
const { reset } = useQueryErrorResetBoundary();

const handleClickReset = () => {
resetErrorBoundary();
reset();
};

return (
<ErrorContainer>
<ErrorTitle>에러가 발생했습니다</ErrorTitle>
<ErrorMessage>{error.message}</ErrorMessage>
<RetryButton onClick={handleClickReset}>다시 시도</RetryButton>
</ErrorContainer>
);
};

const ErrorContainer = styled.div`
padding: 1rem;
border-radius: 0.5rem;
background-color: #fef2f2;
color: #b91c1c;
`;

const ErrorTitle = styled.h2`
font-size: 1.125rem;
font-weight: 600;
margin-bottom: 0.5rem;
`;

const ErrorMessage = styled.p`
margin-bottom: 1rem;
`;

const RetryButton = styled.button`
padding: 0.5rem 1rem;
background-color: #dc2626;
color: white;
border-radius: 0.25rem;
&:hover {
background-color: #b91c1c;
}
`;

export default FetchErrorFallback;
9 changes: 8 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import App from './App';

import theme from 'styles/theme';

const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
},
},
});

// async function enableMocking() {
// if (import.meta.env.MODE !== 'development') return;

Expand Down
16 changes: 14 additions & 2 deletions src/pages/myPage/MyPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import styled from '@emotion/styled';
import { MoonLoader } from 'react-spinners';

import AccountStatus from './components/AccountStatus';
import ApplicationSection from './components/ApplicationSection';
import ManagementSection from './components/ManagementSection';
import UserProfile from './components/UserProfile';

import FetchBoundary from 'components/boundary/FetchBoundary';
import { useGetUserInfo } from 'queries/user/useGetUserInfo';

const MyPage = () => {
return (
<MyPageContainer>
<FetchBoundary>
<MyPageContent />
</FetchBoundary>
</MyPageContainer>
);
};

const MyPageContent = () => {
const { data: userInfo } = useGetUserInfo();

const accountInfo =
Expand All @@ -19,12 +31,12 @@ const MyPage = () => {
: null;

return (
<MyPageContainer>
<>
<UserProfile userInfo={userInfo} />
<AccountStatus accountInfo={accountInfo} />
<ManagementSection />
<ApplicationSection />
</MyPageContainer>
</>
);
};

Expand Down
6 changes: 4 additions & 2 deletions src/queries/user/useGetUserInfo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';
import { useEffect } from 'react';

import { getUserInfo } from 'api/userApi';
Expand All @@ -7,9 +7,11 @@ import { useAuthStore } from 'stores';
export const useGetUserInfo = () => {
const { setUserProfile } = useAuthStore(['setUserProfile']);

const query = useQuery({
const query = useSuspenseQuery({
queryKey: ['userInfo'],
queryFn: getUserInfo,
staleTime: 1000 * 60 * 5, // 5분
gcTime: 1000 * 60 * 30, // 30분
});

useEffect(() => {
Expand Down
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3963,6 +3963,13 @@ react-docgen@^7.0.0:
loose-envify "^1.1.0"
scheduler "^0.23.2"

react-error-boundary@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-5.0.0.tgz#6b6c7e075c922afb0283147e5b084efa44e68570"
integrity sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==
dependencies:
"@babel/runtime" "^7.12.5"

react-hook-form@^7.53.2:
version "7.53.2"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.2.tgz#6fa37ae27330af81089baadd7f322cc987b8e2ac"
Expand Down Expand Up @@ -4008,6 +4015,11 @@ [email protected]:
dependencies:
"@remix-run/router" "1.21.0"

react-spinners@^0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/react-spinners/-/react-spinners-0.15.0.tgz#bb9536a3839ab4e1513bb98847d79cc1fc930b93"
integrity sha512-ZO3/fNB9Qc+kgpG3SfdlMnvTX6LtLmTnOogb3W6sXIaU/kZ1ydEViPfZ06kSOaEsor58C/tzXw2wROGQu3X2pA==

"react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
Expand Down

0 comments on commit be6dac5

Please sign in to comment.