
대단한 건 아니고 개인 포르폴리오 사이트 제작 과정 중 있던 컴포넌트 리팩토링 과정을 뿌듯해서 포스팅하려 한다..
import { MenuList, MenuListItem } from 'react95'
import styled from 'styled-components'
export default function HeaderMenu() {
return (
<MenuListContainer inline fullWidth>
<MenuListItem>File</MenuListItem>
<MenuListItem>Edit</MenuListItem>
<MenuListItem>View</MenuListItem>
<MenuListItem>Help</MenuListItem>
</MenuListContainer>
)
}
const MenuListContainer = styled(MenuList)`
margin: 0;
box-shadow: none;
padding: 0 4px;
border-right: none;
border-left: none;
`
import { MenuList, MenuListItem, Separator } from 'react95'
export default function StartMenu({ onClickStartBtn }) {
const onClickRoutes = url => {
window.open(url)
}
return (
<MenuList
style={{
position: 'absolute',
left: '0',
bottom: '100%',
boxSizing: 'border-box',
margin: '0',
}}
onClick={onClickStartBtn}
>
<MenuListItem onClick={() => onClickRoutes('https://github.com/kangaroo19')}>
<span>👿</span>
Github
</MenuListItem>
<MenuListItem>
<span role="img" aria-label="📁">
📁
</span>
My account
</MenuListItem>
</MenuList>
)
}
MenuList 컴포넌트 안에 MenuListItem 컴포넌트가 들어가는 패턴이 상당히 많이 쓰이고 있는 것을 발견하고
재사용 위해 공통 컴포넌트로 만들어 이를 리팩토링 하려 한다
- MenuList에 프롭으로 inline,fullWidth,스타일 객체,onClick 함수가 들어가야함
- 자식컴포넌트인 MenuListItem 컴포넌트는 동일한 패턴이므로 map함수 사용하여 반복문 돌리면 더 좋을것 같음
- MenuListItem 컴포넌트 또한 안에 랜더링 해줄 값,onClick함수가 들어가야함
- 반복문 돌릴 데이터는 사용하는 곳에서 프롭으로 넣어주면 될듯하다
- 그리고 재사용하기 위해 합성 컴포넌트 패턴으로 공통 컴포넌트로 만들기
위 내용을 기반으로 새로 컴포넌트를 만들어 보았다
MenuListsWrapper ( MenuList에 해당)
import { MenuList } from 'react95'
import MenuListsItem from './components/MenuListsItem'
export default function MenuListsWrapper({ children, fullWidth, inline, style, onClick }) {
return (
<MenuList fullWidth={fullWidth} inline={inline} style={style} onClick={onClick}>
{children}
</MenuList>
)
}
MenuListsWrapper.Item = MenuListsItem
자식 컴포넌트로 MenuListsItem이 들어가는 형태로 구현
styled-component로 만들어 관련 css 속성 값 또한 프롭으로 받을까도 생각했지만
변하는 css 속성값이 일정치 않아 스타일 객체를 받기로 결정하였다
MenuListsItem (MenuListItem에 해당)
import { MenuListItem } from 'react95'
const ItemPropTypes = PropTypes.shape({
onClick: PropTypes.func,
icon: PropTypes.string,
title: PropTypes.string.isRequired,
});
MenuListsItem.propTypes = {
itemObj: ItemPropTypes.isRequired,
};
export default function MenuListsItem({ itemObj }) {
return (
<MenuListItem onClick={itemObj.onClick && itemObj.onClick}>
{itemObj.icon && <span>{itemObj.icon}</span>}
{itemObj.title}
</MenuListItem>
)
}
타입스크립트를 사용하고 있지 않으므로 후일 유지보수성을 위해 prop-types 라이브러리 사용하여 프롭의 값들을 체크해주자
Usage
import MenuListsWrapper from 'components/AppWindow/components/menuList/MenuListsWrapper'
import { useAppWindowRender } from 'utils/zustand/useAppWindowRender'
export default function StartMenu({ onClickStartBtn }) {
const { onClickWindowOpen } = useAppWindowRender()
const MenuListItemArr = [
{ title: 'Github', icon: '👿', onClick: () => window.open('https://github.com/kangaroo19') },
{ title: 'Login', icon: '📁', onClick: () => onClickWindowOpen('loginWindow') },
]
return (
<MenuListsWrapper style={menuListStyle} onClick={onClickStartBtn}>
{MenuListItemArr.map(item => (
<MenuListsWrapper.Item itemObj={item} />
))}
</MenuListsWrapper>
)
}
const menuListStyle = {
margin: '0',
position: 'absolute',
left: '0',
bottom: '100%',
boxSizing: 'border-box',
}
이렇게 함으로써 공통 컴포넌트를 만들어 재사용성을 좀 더 높였다!!
'React' 카테고리의 다른 글
| App.js 다이어트 (1) | 2024.05.03 |
|---|---|
| 깃허브 페이지와 커스텀 도메인 (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 |