Skip to content

Commit

Permalink
hotfix: 잘못된 id의 상점 접근 시 에러 처리 및 슬랙 오류 호출 시점 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
chaeseungyun committed Jan 30, 2025
1 parent 681bc3f commit 2c3939f
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 17 deletions.
2 changes: 2 additions & 0 deletions src/components/common/ErrorBoundary/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { ErrorInfo } from 'react';
import showToast from 'utils/ts/showToast';
import { AxiosError } from 'axios';
import { sendClientError } from '@bcsdlab/koin';

interface Props {
fallbackClassName: string;
Expand Down Expand Up @@ -33,6 +34,7 @@ export default class ErrorBoundary extends React.Component<Props, State> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
componentDidCatch(error: AxiosError<any, any> | Error, __: ErrorInfo) {
showToast('error', isAxiosError(error) ? error.response?.data.error.message : error.message);
sendClientError(error);
}

render() {
Expand Down
6 changes: 1 addition & 5 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import './index.scss';
import { BrowserRouter } from 'react-router-dom';
import PortalProvider from 'components/common/Modal/PortalProvider';
import { RecoilRoot } from 'recoil';
import { QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { sendClientError } from '@bcsdlab/koin';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App';
import reportWebVitals from './reportWebVitals';

Expand All @@ -16,9 +15,6 @@ const queryClient = new QueryClient({
retry: false,
},
},
queryCache: new QueryCache({
onError: (error) => sendClientError(error),
}),
});

const root = ReactDOM.createRoot(
Expand Down
37 changes: 25 additions & 12 deletions src/pages/Store/StoreDetailPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef } from 'react';
import React, { Suspense, useEffect, useRef } from 'react';
import getDayOfWeek from 'utils/ts/getDayOfWeek';
import ImageModal from 'components/common/Modal/ImageModal';
import {
Expand All @@ -21,6 +21,8 @@ import { useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
import * as api from 'api';
import useTokenState from 'utils/hooks/state/useTokenState';
import { useABTestView } from 'utils/hooks/abTest/useABTestView';
// eslint-disable-next-line
import StoreDetailBoundary from '../components/StoreDetailBoundary/StoreDetailBoundary';
import MenuTable from './MenuTable';
import EventTable from './EventTable';
import styles from './StoreDetailPage.module.scss';
Expand All @@ -37,7 +39,7 @@ function StoreDetailPage() {
const logger = useLogger();
// waterfall 현상 막기
const { data: paralleData } = useSuspenseQuery({
queryKey: ['storeDetail', 'storeDetailMenu', 'review'],
queryKey: ['storeDetail', 'storeDetailMenu', 'review', params.id],
queryFn: () => Promise.all([
queryClient.fetchQuery({
queryKey: ['storeDetail', params.id],
Expand Down Expand Up @@ -410,18 +412,29 @@ function StoreDetailPage() {
{tapType === '리뷰' && <ReviewPage id={params.id!} />}
</div>
{testValue === 'call_floating' && (
<a
role="button"
aria-label="상점 전화하기"
href={`tel:${storeDetail?.phone}`}
onClick={onClickCallNumber}
className={styles['phone-button--floating']}
>
<Phone />
</a>
<a
role="button"
aria-label="상점 전화하기"
href={`tel:${storeDetail?.phone}`}
onClick={onClickCallNumber}
className={styles['phone-button--floating']}
>
<Phone />
</a>
)}
</div>
);
}

export default StoreDetailPage;
function StoreDetail() {
const navigate = useNavigate();
return (
<StoreDetailBoundary onErrorClick={() => navigate('/store')}>
<Suspense fallback={<div />}>
<StoreDetailPage />
</Suspense>
</StoreDetailBoundary>
);
}

export default StoreDetail;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
height: 60vh;
}

.button {
color: #fff;
font-size: 15px;
text-decoration: none;
cursor: pointer;
width: 88px;
height: 36px;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
background-color: #175c8e;
margin-top: 25px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { ErrorInfo } from 'react';
import { AxiosError } from 'axios';
import showToast from 'utils/ts/showToast';
import { isKoinError, sendClientError } from '@bcsdlab/koin';
import styles from './StoreDetailBoundary.module.scss';

interface Props {
onErrorClick: () => void;
children: React.ReactNode;
}

interface State {
hasError: boolean;
status?: number;
}

function isAxiosError(error: AxiosError<any, any> | Error): error is AxiosError<any, any> {
return ('response' in error);
}

export default class StoreDetailBoundary extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}

// 이후에 사용시 해제
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static getDerivedStateFromError(error: Error) {
if (isKoinError(error) || isAxiosError(error)) {
return { hasError: true, status: error.status };
}
return { hasError: true };
}

// 이후에 사용시 해제
// eslint-disable-next-line @typescript-eslint/no-unused-vars
componentDidCatch(error: Error, __: ErrorInfo) {
showToast('error', error.message);
sendClientError(error);
}

render() {
const { children, onErrorClick } = this.props;
const { hasError, status } = this.state;

if (hasError && status === 404) {
return (
<div className={styles.container}>
<h1>존재하지 않는 상점입니다.</h1>
<button
className={styles.button}
type="button"
onClick={onErrorClick}
>
상점 목록
</button>
</div>
);
}

if (hasError) {
return <div className={styles.container}>오류가 발생했습니다</div>;
}

return children;
}
}

0 comments on commit 2c3939f

Please sign in to comment.