
개인적으로 app.js는 간결하고 가독성이 좋은 것을 선호하지만
막~~ 개발을 열심히 하다보면 어느 순간...
import { ThemeProvider } from 'styled-components'
import original from 'react95/dist/themes/original'
import Layout from './components/layout/Layout'
import BgIcon from 'components/bgIcon/BgIcon'
import myComputer from 'asset/images/myComputer.png'
import trashIcon from 'asset/images/trash.png'
import networkIcon from 'asset/images/network.png'
import { useAppWindowRender } from 'utils/zustand/useAppWindowRender'
import MyProjectsWindow from 'components/AppWindow/windows/MyProjectsWindow'
import MyInfoWindow from 'components/AppWindow/windows/MyInfoWindow'
import TrashCanWindow from 'components/AppWindow/windows/TrashCanWindow'
import notePadIcon from 'asset/images/notepad.png'
import GuestBookWindow from 'components/AppWindow/windows/GuestBookWindow'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import BlogWindow from 'components/AppWindow/windows/BlogWindow'
import neki from 'asset/images/네키.png'
import { Route, Routes, useNavigate } from 'react-router-dom'
import LoginWindow from 'components/AppWindow/windows/login/LoginWindow'
import useEscapeKey from 'utils/hook/useEsacpeKey'
export default function App() {
const { windowRenderObj, onClickWindowOpen, closeAllWindow } = useAppWindowRender()
const queryClient = new QueryClient()
const navigate = useNavigate()
useEscapeKey(closeAllWindow)
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={original}>
<Layout>
<Layout.WindowContainer>
<BgIcon
title="내 정보"
imgObj={{ src: myComputer, alt: 'myComputer' }}
onDoubleClick={() => onClickWindowOpen('myInfoWindow')}
border="1px solid rgb(0, 128, 128)"
color="white"
/>
<BgIcon
title="내 프로젝트"
imgObj={{ src: networkIcon, alt: 'networkIcon' }}
onDoubleClick={() => onClickWindowOpen('myProjectWindow')}
border="1px solid rgb(0, 128, 128)"
color="white"
/>
<BgIcon
title="방명록"
imgObj={{ src: notePadIcon, alt: 'trashicon' }}
onDoubleClick={() => onClickWindowOpen('guestBookWindow')}
border="1px solid rgb(0, 128, 128)"
color="white"
/>
<BgIcon
title="블로그"
imgObj={{ src: neki, alt: 'trashicon' }}
onDoubleClick={() => {
onClickWindowOpen('blogWindow')
navigate('/blog')
}}
border="1px solid rgb(0, 128, 128)"
color="white"
/>
<BgIcon
title="휴지통"
imgObj={{ src: trashIcon, alt: 'trashicon' }}
onDoubleClick={() => onClickWindowOpen('trashCanWindow')}
border="1px solid rgb(0, 128, 128)"
color="white"
/>
{windowRenderObj.myInfoWindow.isOpen && <MyInfoWindow />}
{windowRenderObj.myProjectWindow.isOpen && <MyProjectsWindow />}
{windowRenderObj.trashCanWindow.isOpen && <TrashCanWindow />}
{windowRenderObj.guestBookWindow.isOpen && <GuestBookWindow />}
{windowRenderObj.loginWindow.isOpen && <LoginWindow/>}
</Layout.WindowContainer>
<Layout.TaskBar />
<Routes>
<Route path="/blog/*" element={windowRenderObj.blogWindow.isOpen && <BlogWindow />} />
</Routes>
</Layout>
</ThemeProvider>
</QueryClientProvider>
)
}
이렇게 더러워진다... 무수한 import문을 보면 정말 정신이 아득해진다 (import문만 거진 20줄..ㅋㅋㅋ)
일단 위의 더러운 코드를 세 부분으로 나누어 따로 컴포넌트를 만들어 세 컴포넌트만 import 해주는 방식으로 하려한다
- 아이콘을 랜더링 해주는 <BgIcon/> 만을 모아둔 컴포넌트, 그리고 border,color 프롭처럼 반복되는 부분은 제거하자
- 아이콘 더블 클릭 시 랜더링되는 윈도우 창을 모아둔 컴포넌트
- routes 컴포넌트
이렇게만 나눠도 우리의 App.js는 많이 깔끔해질것 같다
BgIcon 컴포넌트
import styles from './Background.module.css'
import { useAppWindowRender } from 'utils/zustand/useAppWindowRender'
import BgIcon from 'components/layout/background/components/BgIcon'
import myComputer from 'asset/images/myComputer.png'
import trashIcon from 'asset/images/trash.png'
import networkIcon from 'asset/images/network.png'
import neki from 'asset/images/네키.png'
import { useNavigate } from 'react-router-dom'
export default function Background() {
const { onClickWindowOpen } = useAppWindowRender()
const navigate = useNavigate()
const bgIconArr = [
{
title: '내 정보',
imgObj: { src: myComputer, alt: 'myComputer' },
onDoubleClick: () => onClickWindowOpen('myInfoWindow'),
},
{
title: '내 프로젝트',
imgObj: { src: networkIcon, alt: 'networkIcon' },
onDoubleClick: () => onClickWindowOpen('myProjectWindow'),
},
{
title: '방명록',
imgObj: { src: networkIcon, alt: 'networkIcon' },
onDoubleClick: () => onClickWindowOpen('guestBookWindow'),
},
{
title: '블로그',
imgObj: { src: neki, alt: 'nekiIcon' },
onDoubleClick: () => {
onClickWindowOpen('blogWindow')
navigate('/blog')
},
},
{
title: '휴지통',
imgObj: { src: trashIcon, alt: 'trashicon' },
onDoubleClick: () => onClickWindowOpen('trashCanWindow'),
},
]
return (
<div className={styles.boxContainer}>
{bgIconArr.map(item => (
<BgIcon title={item.title} imgObj={item.imgObj} onDoubleClick={item.onDoubleClick} />
))}
</div>
)
}
배열 객체를 만들어 map함수로 랜더링되게 처리하였고 border와 color 프롭은 제거하였다
WindowRender 컴포넌트
import { Suspense, lazy } from 'react'
import { useAppWindowRender } from 'utils/zustand/useAppWindowRender'
const GuestBookWindow = lazy(() => import('components/AppWindow/windows/GuestBookWindow'))
const MyInfoWindow = lazy(() => import('components/AppWindow/windows/MyInfoWindow'))
const MyProjectsWindow = lazy(() => import('components/AppWindow/windows/MyProjectsWindow'))
const TrashCanWindow = lazy(() => import('components/AppWindow/windows/TrashCanWindow'))
const LoginWindow = lazy(() => import('components/AppWindow/windows/login/LoginWindow'))
export default function WindowRender() {
const { windowRenderObj } = useAppWindowRender()
return (
<Suspense>
{windowRenderObj.myInfoWindow.isOpen && <MyInfoWindow />}
{windowRenderObj.myProjectWindow.isOpen && <MyProjectsWindow />}
{windowRenderObj.trashCanWindow.isOpen && <TrashCanWindow />}
{windowRenderObj.guestBookWindow.isOpen && <GuestBookWindow />}
{windowRenderObj.loginWindow.isOpen && <LoginWindow />}
</Suspense>
)
}
각 윈도우 컴포넌트들은 특정 조건을 만족했을 때만 랜더링되므로 성능을 위해 동적 임포트를 사용하여 구현하였다
Routes 컴포넌트
import BlogWindow from 'components/AppWindow/windows/BlogWindow'
import { Route, Routes } from 'react-router-dom'
import { useAppWindowRender } from 'utils/zustand/useAppWindowRender'
export default function AppRouter() {
const { windowRenderObj } = useAppWindowRender()
return (
<Routes>
<Route path="/blog/*" element={windowRenderObj.blogWindow.isOpen && <BlogWindow />} />
</Routes>
)
}
위와 동일하게 라우팅을 담당하는 부분만 따로 뺐다
App.js
import { ThemeProvider } from 'styled-components'
import original from 'react95/dist/themes/original'
import Layout from './components/layout/Layout'
import { useAppWindowRender } from 'utils/zustand/useAppWindowRender'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import useEscapeKey from 'utils/hook/useEsacpeKey'
import AppRouter from 'routes/AppRouter'
export default function App() {
const { closeAllWindow } = useAppWindowRender()
const queryClient = new QueryClient()
useEscapeKey(closeAllWindow)
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={original}>
<Layout>
<Layout.Background />
<Layout.WindowRender />
<Layout.TaskBar />
<AppRouter />
</Layout>
</ThemeProvider>
</QueryClientProvider>
)
}
복잡하던 app.js가 상당히 간결해진 것을 확인 할 수 있다
'React' 카테고리의 다른 글
컴포넌트 리팩토링 과정 (0) | 2024.05.02 |
---|---|
깃허브 페이지와 커스텀 도메인 (0) | 2024.04.03 |
react-hook-form,react-query 사용한 몬스터도감 만들기 (2) (0) | 2024.03.26 |
react-hook-form,react-query 사용한 몬스터도감 만들기 (1) (1) | 2024.03.22 |
react-hook-form을 이용한 인풋 컴포넌트 구현 (0) | 2024.03.20 |