Skip to content
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

[# 326] 라우트 배열로 분리 후 타입 세이프 라우팅 구현 #327

Merged
merged 4 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 25 additions & 204 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
import { lazy, Suspense, useCallback, useEffect } from 'react';
import { Suspense, useCallback, useEffect } from 'react';

import { BrowserRouter, Route, Routes } from 'react-router-dom';

import ModifyNickname from './components/profile/ModifyNickname';
import PrivateRoute from '@/routes/PrivateRoute.tsx';

import Main from './pages/Main';
import LoginPage from '@/pages/LoginPage.tsx';
import LoginRedirectPage from '@/pages/LoginRedirectPage.tsx';
import { routes } from '@/constants/routes.tsx';
import LoadingSpinner from '@/components/LoadingSpinner.tsx';

const AddPlantPage = lazy(() => import('./pages/AddPlantPage'));
const MyPlant = lazy(() => import('./pages/MyPlant'));
const GuideDetails = lazy(() => import('./pages/GuideDetails'));
const Guide = lazy(() => import('./pages/Guide'));
const MyPlantDetail = lazy(() => import('@/pages/MyPlantDetail.tsx'));
const Profile = lazy(() => import('./pages/Profile'));
const RegisterPage = lazy(() => import('@/pages/RegisterPage.tsx'));
const MyPlantEdit = lazy(() => import('@/pages/MyPlantEdit.tsx'));
const ErrorPage = lazy(() => import('./pages/ErrorPage'));
const AlimDetail = lazy(() => import('@/pages/AlimDetail.tsx'));
const 서비스이용약관페이지 = lazy(() => import('./pages/서비스이용약관페이지'));
const 개인정보처리방침페이지 = lazy(() => import('@/pages/개인정보처리방침페이지.tsx'));
const MyPlantFeedPage = lazy(() => import('@/pages/MyPlantFeedPage.tsx'));
import ErrorPage from '@/pages/ErrorPage.tsx';

function App() {
const refresh = useCallback(() => {
Expand All @@ -44,192 +26,31 @@ function App() {
return (
<BrowserRouter>
<Routes>
<Route
path="/"
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<PrivateRoute>
<Main />
</PrivateRoute>
}
/>
<Route
path={'/my-plant/add'}
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<AddPlantPage />
</PrivateRoute>
</Suspense>
}
/>
<Route
path="my-plant"
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<MyPlant />
</PrivateRoute>
</Suspense>
}
/>
<Route
path={'/my-plant/:plantId'}
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<MyPlantDetail />
</PrivateRoute>
</Suspense>
}
/>
<Route
path={'/my-plant/:plantId/feed'}
element={
<Suspense fallback={<LoadingSpinner />}>
<MyPlantFeedPage />
</Suspense>
}
/>
<Route
path={'/my-plant/edit/:myPlantId'}
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<MyPlantEdit />
</PrivateRoute>
</Suspense>
}
/>
<Route
path="/guide/:id"
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<GuideDetails />
</PrivateRoute>
</Suspense>
}
/>
<Route
path="/guide"
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<Guide />
</PrivateRoute>
</Suspense>
}
/>
<Route path="/login" element={<LoginPage />} />
<Route path={'/redirect'} element={<LoginRedirectPage />} />
<Route path={'/login/register'} element={<RegisterPage />} />
<Route
path="/profile"
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<Profile />
</PrivateRoute>
</Suspense>
}
/>
<Route
path="/profile/edit"
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
{routes.map((route) => {
let component = route.element;

if (route.private) {
component = <PrivateRoute>{component}</PrivateRoute>;
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<ModifyNickname />
</PrivateRoute>
</Suspense>

if (route.suspense) {
component = <Suspense fallback={<LoadingSpinner />}>{component}</Suspense>;
}
/>
<Route
path={'/profile/notification'}
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}

return (
<Route
path={route.path}
element={component}
key={route.path}
errorElement={
<ErrorPage
error={new Error('에러가 발생했습니다. 다시 시도해 주세요.')}
reset={refresh}
/>
}
/>
}
element={
<Suspense fallback={<LoadingSpinner />}>
<PrivateRoute>
<AlimDetail />
</PrivateRoute>
</Suspense>
}
/>
<Route
path={'/terms/service'}
element={
<Suspense fallback={<LoadingSpinner />}>
<서비스이용약관페이지 />
</Suspense>
}
/>
<Route
path="/terms/privacy"
element={
<Suspense fallback={<LoadingSpinner />}>
<개인정보처리방침페이지 />
</Suspense>
}
/>
<Route path="/*" element={<ErrorPage />} />
);
})}
</Routes>
</BrowserRouter>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/myPlantEdit/ImageInputWithList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const ImageInputWithList = ({ images, plantId }: ImageInputWithListProps) => {
)}
{images.slice(0, 2).map((image) => (
<img
key={`${image.imageUrl}-${image.createdDate}`}
src={image.imageUrl}
alt={'my plant image list'}
className={'w-16 aspect-square border border-GrayOpacity100 rounded-[10px]'}
Expand Down
134 changes: 134 additions & 0 deletions src/constants/routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { lazy } from 'react';

import ModifyNickname from '@/components/profile/ModifyNickname';

import Main from '@/pages/Main';
import LoginPage from '@/pages/LoginPage.tsx';
import LoginRedirectPage from '@/pages/LoginRedirectPage.tsx';

const AddPlantPage = lazy(() => import('@/pages/AddPlantPage'));
const MyPlant = lazy(() => import('@/pages/MyPlant'));
const GuideDetails = lazy(() => import('@/pages/GuideDetails'));
const Guide = lazy(() => import('@/pages/Guide'));
const MyPlantDetail = lazy(() => import('@/pages/MyPlantDetail.tsx'));
const Profile = lazy(() => import('@/pages/Profile'));
const RegisterPage = lazy(() => import('@/pages/RegisterPage.tsx'));
const MyPlantEdit = lazy(() => import('@/pages/MyPlantEdit.tsx'));
const ErrorPage = lazy(() => import('@/pages/ErrorPage'));
const AlimDetail = lazy(() => import('@/pages/AlimDetail.tsx'));
const 서비스이용약관페이지 = lazy(() => import('@/pages/서비스이용약관페이지'));
const 개인정보처리방침페이지 = lazy(() => import('@/pages/개인정보처리방침페이지.tsx'));
const MyPlantFeedPage = lazy(() => import('@/pages/MyPlantFeedPage.tsx'));

// 라우트 배열 정의
export const routes = [
{
path: '/' as const,
element: <Main />,
private: true,
suspense: false,
},
// ------내 식물 관련 페이지------
{
path: '/my-plant' as const,
element: <MyPlant />,
private: true,
suspense: true,
},
{
path: '/my-plant/add' as const,
element: <AddPlantPage />,
private: true,
suspense: true,
},
//------내식물 상세 관련 페이지------
{
path: '/my-plant/:plantId' as const,
element: <MyPlantDetail />,
private: true,
suspense: true,
},
{
path: '/my-plant/:plantId/feed' as const,
element: <MyPlantFeedPage />,
private: true,
suspense: true,
},
{
path: '/my-plant/edit/:myPlantId' as const,
element: <MyPlantEdit />,
private: true,
suspense: true,
},
// ------가이드 관련 페이지------
{
path: '/guide' as const,
element: <Guide />,
private: true,
suspense: true,
},
{
path: '/guide/:id' as const,
element: <GuideDetails />,
private: true,
suspense: true,
},
// ------로그인 관련 페이지------
{
path: '/login' as const,
element: <LoginPage />,
private: false,
suspense: false,
},
{
path: '/redirect' as const,
element: <LoginRedirectPage />,
private: false,
suspense: false,
},
{
path: '/login/register' as const,
element: <RegisterPage />,
private: false,
suspense: false,
},
// ------프로필 관련 페이지------
{
path: '/profile' as const,
element: <Profile />,
private: true,
suspense: true,
},
{
path: '/profile/edit' as const,
element: <ModifyNickname />,
private: true,
suspense: true,
},
{
path: '/profile/notification' as const,
element: <AlimDetail />,
private: true,
suspense: true,
},
// ------약관 관련 페이지------
{
path: '/terms/service' as const,
element: <서비스이용약관페이지 />,
private: false,
suspense: true,
},
{
path: '/terms/privacy' as const,
element: <개인정보처리방침페이지 />,
private: false,
suspense: true,
},
// ------에러 페이지------
{
path: '/*' as const,
element: <ErrorPage />,
private: false,
suspense: false,
},
];
Loading
Loading