-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FE] 리뷰 상세 페이지에 react-query 추가 및 리팩토링 #161
Changes from all commits
e3eaa42
0cb8d19
0a4cec6
19fa32b
339c22c
90f1784
f2e96a7
9721bda
9e31285
251af38
e45ddb4
41d8fb8
54d927c
df18d3a
da20f40
3783ed7
80ca5a2
528eb22
6af1a65
91d0a55
d13fdfd
f20698f
f552fcf
d6d7696
9745350
67e2c5a
4415a36
872ff0b
bc93a51
3032874
52f8de6
c148246
0da75a9
88a2c23
79ee76b
abe9154
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import * as S from './styles'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comments 👍👍 전혀 몰랐읍니다 |
||
|
||
interface RevieweeCommentsProps { | ||
comment: string; | ||
} | ||
|
||
const DEFAULT_COMMENTS = '안녕하세요! 리뷰 잘 부탁드립니다.'; | ||
|
||
const RevieweeComments = ({ comment }: RevieweeCommentsProps) => { | ||
return <S.RevieweeComments>{comment || DEFAULT_COMMENTS}</S.RevieweeComments>; | ||
}; | ||
|
||
export default RevieweeComments; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { FallbackProps } from 'react-error-boundary'; | ||
import { useNavigate } from 'react-router'; | ||
|
||
import ErrorSection from '../ErrorSection'; | ||
|
||
const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => { | ||
const navigate = useNavigate(); | ||
const handleGoHome = () => { | ||
resetErrorBoundary(); | ||
navigate('/'); //TODO : 홈 페이지 경로가 결정되면 변경 | ||
}; | ||
Comment on lines
+6
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. errorBoundary에 전달되는 |
||
|
||
return <ErrorSection errorMessage={error.message} handleGoHome={handleGoHome} handleReload={resetErrorBoundary} />; | ||
}; | ||
|
||
export default ErrorFallback; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { QueryErrorResetBoundary } from '@tanstack/react-query'; | ||
import { Suspense } from 'react'; | ||
import { ErrorBoundary } from 'react-error-boundary'; | ||
|
||
import LoadingPage from '@/pages/LoadingPage'; | ||
import { EssentialPropsWithChildren } from '@/types'; | ||
|
||
import ErrorFallback from '../ErrorFallback'; | ||
|
||
const ErrorSuspenseContainer = ({ children }: EssentialPropsWithChildren) => { | ||
return ( | ||
<QueryErrorResetBoundary> | ||
{({ reset }) => ( | ||
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={reset}> | ||
<Suspense fallback={<LoadingPage />}>{children}</Suspense> | ||
</ErrorBoundary> | ||
)} | ||
</QueryErrorResetBoundary> | ||
); | ||
}; | ||
|
||
export default ErrorSuspenseContainer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { default as ErrorSection } from './ErrorSection'; | ||
export { default as ErrorSuspenseContainer } from './ErrorSuspenseContainer'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './layouts'; | ||
export * from './common'; | ||
export * from './error'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './page'; | ||
export * from './apiErrorMessage'; | ||
export * from './review'; | ||
export * from './queryKeys'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const REVIEW_QUERY_KEYS = { | ||
detailedReview: 'detailedReview', | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,30 @@ | ||
import { Global, ThemeProvider } from '@emotion/react'; | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom/client'; | ||
import { createBrowserRouter, RouterProvider } from 'react-router-dom'; | ||
|
||
import App from '@/App'; | ||
|
||
import { ErrorSuspenseContainer } from './components'; | ||
import DetailedReviewPage from './pages/DetailedReviewPage'; | ||
import ErrorPage from './pages/ErrorPage'; | ||
import ReviewPreviewListPage from './pages/ReviewPreviewListPage'; | ||
import ReviewWritingPage from './pages/ReviewWriting'; | ||
import globalStyles from './styles/globalStyles'; | ||
import theme from './styles/theme'; | ||
|
||
const queryClient = new QueryClient({ | ||
defaultOptions: { | ||
queries: { | ||
throwOnError: true, | ||
}, | ||
mutations: { | ||
throwOnError: true, | ||
}, | ||
}, | ||
}); | ||
|
||
const router = createBrowserRouter([ | ||
{ | ||
path: '/', | ||
|
@@ -32,7 +45,11 @@ const router = createBrowserRouter([ | |
}, | ||
{ | ||
path: 'user/detailed-review/:id', | ||
element: <DetailedReviewPage />, | ||
element: ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 무사히 적용돼서 다행입니다!! |
||
<ErrorSuspenseContainer> | ||
<DetailedReviewPage /> | ||
</ErrorSuspenseContainer> | ||
), | ||
}, | ||
], | ||
}, | ||
|
@@ -42,9 +59,11 @@ const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) | |
|
||
root.render( | ||
<React.StrictMode> | ||
<ThemeProvider theme={theme}> | ||
<Global styles={globalStyles} /> | ||
<RouterProvider router={router} /> | ||
</ThemeProvider> | ||
<QueryClientProvider client={queryClient}> | ||
<ThemeProvider theme={theme}> | ||
<Global styles={globalStyles} /> | ||
<RouterProvider router={router} /> | ||
</ThemeProvider> | ||
</QueryClientProvider> | ||
</React.StrictMode>, | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,14 +2,32 @@ import { http, HttpResponse } from 'msw'; | |
|
||
import endPoint from '@/apis/endpoints'; | ||
|
||
import { DETAILED_REVIEW_MOCK_DATA } from '../mockData/detailedReviewMockData'; | ||
import { | ||
DETAILED_REVIEW_MOCK_DATA, | ||
DETAILED_PAGE_MOCK_API_SETTING_VALUES, | ||
DETAILED_PAGE_ERROR_API_VALUES, | ||
} from '../mockData/detailedReviewMockData'; | ||
import { REVIEW_PREVIEW_LIST } from '../mockData/reviewPreviewList'; | ||
import { REVIEW_WRITING_DATA } from '../mockData/reviewWritingData'; | ||
|
||
const getDetailedReview = () => | ||
http.get(endPoint.gettingDetailedReview(123456, 123456), async ({ request }) => { | ||
return HttpResponse.json(DETAILED_REVIEW_MOCK_DATA); | ||
}); | ||
http.get( | ||
endPoint.gettingDetailedReview( | ||
DETAILED_PAGE_MOCK_API_SETTING_VALUES.reviewId, | ||
DETAILED_PAGE_MOCK_API_SETTING_VALUES.memberId, | ||
), | ||
async () => { | ||
return HttpResponse.json(DETAILED_REVIEW_MOCK_DATA); | ||
}, | ||
); | ||
|
||
const getWrongDetailReview = () => | ||
http.get( | ||
endPoint.gettingDetailedReview(DETAILED_PAGE_ERROR_API_VALUES.reviewId, DETAILED_PAGE_ERROR_API_VALUES.memberId), | ||
async () => { | ||
return HttpResponse.json({ error: '잘못된 상세리뷰 요청' }, { status: 404 }); | ||
}, | ||
); | ||
Comment on lines
+24
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 잘못된 요청에 대한 에러를 반환하는 핸들러를 만들었군요!
Comment on lines
+24
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러가 발생했을 때의 핸들러도 만들어주셨네요👍 |
||
|
||
const getDataToWriteReview = () => | ||
http.get(endPoint.gettingDataToWriteReview(10), async ({ request }) => { | ||
|
@@ -21,6 +39,6 @@ const getReviewPreviewList = () => | |
return HttpResponse.json(REVIEW_PREVIEW_LIST); | ||
}); | ||
|
||
const reviewHandler = [getDetailedReview(), getReviewPreviewList(), getDataToWriteReview()]; | ||
const reviewHandler = [getDetailedReview(), getWrongDetailReview(), getReviewPreviewList(), getDataToWriteReview()]; | ||
|
||
export default reviewHandler; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,35 @@ | ||
import { DetailReviewData } from '@/types'; | ||
|
||
export const DETAILED_PAGE_MOCK_API_SETTING_VALUES = { | ||
reviewId: 5, | ||
memberId: 2, | ||
}; | ||
|
||
export const DETAILED_PAGE_ERROR_API_VALUES = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상수화가 잘 되어있어서 아래 모킹 핸들러에서 의도를 파악하기가 더 쉬웠어요~~ 굿굿 |
||
reviewId: 0, | ||
memberId: 0, | ||
}; | ||
|
||
const ANSWER = | ||
'림순의 바람은 그윽한 산들바람처럼 잔잔하게 흘러갔습니다. \n 눈부신 햇살이 그의 어깨를 감싸며, 푸른 하늘 아래 펼쳐진 들판을 바라보았습니다.\n 그의 마음은 자연의 아름다움 속에서 평온을 찾았고, 그 순간마다 삶의 소중함을 느꼈습니다.\n 그는 늘 그러한 순간들을 기억하며, 미래의 나날들을 기대했습니다. \n 바람은 여전히 그를 감싸며, 그의 마음 속 깊은 곳에 있는 꿈과 희망을 불러일으켰습니다.\n 림순은 미소 지으며 앞으로 나아갔습니다.림순의 바람은 그윽한 산들바람처럼 잔잔하게 흘러갔습니다. \n 눈부신 햇살이 그의 어깨를 감싸며, 푸른 하늘 아래 펼쳐진 들판을 바라보았습니다.\n 그의 마음은 자연의 아름다움 속에서 평온을 찾았고, 그 순간마다 삶의 소중함을 느꼈습니다.\n 그는 늘 그러한 순간들을 기억하며, 미래의 나날들을 기대했습니다. 림순의 바람은 그윽한 산들바람처럼 잔잔하게 흘러갔습니다. \n 눈부신 햇살이 그의 어깨를 감싸며, 푸른 하늘 아래 펼쳐진 들판을 바라보았습니다.\n 그의 마음은 자연의 아름다움 속에서 평온을 찾았고, 그 순간마다 삶의 소중함을 느꼈습니다.\n 그는 늘 그러한 순간들을 기억하며, 미래의 나날들을 기대했습니다. \n 바람은 여전히 그를 감싸며, 그의 마음 속 깊은 곳에 있는 꿈과 희망을 불러일으켰습니다.\n 림순은 미소 지으며 앞으로 나아갔습니다.림순의 바람은 그윽한 산들바람처럼 잔잔하게 흘러갔습니다. \n 눈부신 햇살이 그의 어깨를 감싸며, 푸른 하늘 아래 펼쳐진 들판을 바라보았습니다.\n 그의 마음은 자연의 아름다움 속에서 평온을 찾았고, 그 순간마다 삶의 소중함을 느꼈습니다.\n 그는 늘 그러한 순간들을 기억하며, 미래의 나날들을 기대했습니다. '; | ||
|
||
export const DETAILED_REVIEW_MOCK_DATA: DetailReviewData = { | ||
id: 123456, | ||
createdAt: new Date('2024-07-16'), | ||
isPublic: false, | ||
reviewerGroup: { | ||
id: 123456, | ||
name: 'review-me', | ||
description: 'vite 쓰고 싶다.', | ||
thumnailUrl: '', | ||
}, | ||
reviews: [ | ||
revieweeName: 'badahertz52', | ||
projectName: 'review-me', | ||
contents: [ | ||
{ | ||
id: 1, | ||
question: '[공개] 동료의 개발 역량 향상을 위해 피드백을 남겨 주세요.', | ||
answer: ANSWER, | ||
}, | ||
{ question: '[공개] 동료의 소프트 스킬의 성장을 위해 피드백을 남겨 주세요.', answer: ANSWER }, | ||
{ question: '[비공개] 팀 동료로 근무한다면 같이 일 하고 싶은 개발자인가요?', answer: ANSWER }, | ||
|
||
{ id: 2, question: '[공개] 동료의 소프트 스킬의 성장을 위해 피드백을 남겨 주세요.', answer: ANSWER }, | ||
{ id: 3, question: '[비공개] 팀 동료로 근무한다면 같이 일 하고 싶은 개발자인가요?', answer: ANSWER }, | ||
], | ||
keywords: [ | ||
{ id: 11, detail: '친절해요' }, | ||
{ id: 22, detail: '이야기를 잘 들어줘요.' }, | ||
], | ||
keywords: ['친절해요', '친절합니다!', '친절해요요요요요', '친절해해해해해', '친절해요요용'], | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추후에 필요한 queryString을 위와 같이 객체 형태로 받아, 요청 URL을 만들어주는 유틸 함수를 만들어도 좋을 것 같아요!