홈페이지에서 많이 볼 수 있는 상단에 위치한 메뉴바이다.
이를 구현하기 위해 필요한 것들은 각 요소의 컴포넌트와 버튼 클릭 이벤트이다.
function MenuHeader() {
const navigate = useNavigate();
const handleSearch = () => {
alert('삐용');
//라우트 설정 완료되면 주석 해젷 사용하심 될 것 같습니다 !
//navigate('/search');
};
const handleCalendar = () => {
navigate('/calendar');
};
const handleMyPage = () => {
navigate('/myPage');
};
const handleMain = () => {
navigate('/main');
};
const getSegment = () => {
const location = useLocation();
const path = location.pathname;
const segments = path.split('/').filter(Boolean);
const firstSegment = segments[0];
return firstSegment;
}
const segment = getSegment();
return(
<S.MenuHeaderWrapper>
<BtnSearch onClick={handleSearch}/>
{
segment === 'main'
?
<BtnCalendar onClick={handleCalendar} />
:
<BtnHomeIcon onClick={handleMain} />
}
<BtnMyPage onClick={handleMyPage} />
</S.MenuHeaderWrapper>
);
}
export default MenuHeader;
기존 코드이다. 버튼 컴포넌트들은 모두 import 해온 상태이다.
버튼 클릭 이벤트 함수의 경우 모두 navigate 동작만 수행하는 간단하고 동일한 구조이지만 반복되어 선언되었다.
각 요소의 필요한 값들을 배열로 선언한 후, map 메소드를 통하여 동일하게 구현할 수 있다.
const menuItems = [
{
id: 'search',
component: BtnSearch,
onClick: () => {alert('검색');},
},
{
id: 'calendar',
component: BtnCalendar,
onClick: () => {navigate('/calendar');},
condition: segment === 'main',
},
{
id: 'main',
component: BtnHomeIcon,
onClick: () => {navigate('/main');},
condition: segment !=='main',
},
{
id: 'myPage',
component: BtnMyPage,
onClick: () => {navigate('/myPage');},
},
];
필요한 요소들을 담은 menuItems 배열이다.
onClick 함수 역시 비교적 간단하기 때문에 바로 정의해주었다.
key 값을 위한 id 프로퍼티도 정의하였다.
return(
<S.MenuHeaderWrapper>
{
menuItems.filter(menu => menu.condition !== false)
.map((menuItem) => (
<menuItem.component
key={menuItem.id}
onClick={menuItem.onClick}
/>
))
}
</S.MenuHeaderWrapper>
);
map 메소드를 통하여 렌더링하였다.
전체코드!
function MenuHeader() {
const navigate = useNavigate();
const getSegment = () => {
const location = useLocation();
const path = location.pathname;
const segments = path.split('/').filter(Boolean);
const firstSegment = segments[0];
return firstSegment;
}
const segment = getSegment();
const menuItems = [
{
id: 'search',
component: BtnSearch,
onClick: () => {alert('검색');},
},
{
id: 'calendar',
component: BtnCalendar,
onClick: () => {navigate('/calendar');},
condition: segment === 'main',
},
{
id: 'main',
component: BtnHomeIcon,
onClick: () => {navigate('/main');},
condition: segment !=='main',
},
{
id: 'myPage',
component: BtnMyPage,
onClick: () => {navigate('/myPage');},
},
];
return(
<S.MenuHeaderWrapper>
{
menuItems.filter(menu => menu.condition !== false)
.map((menuItem) => (
<menuItem.component
key={menuItem.id}
onClick={menuItem.onClick}
/>
))
}
</S.MenuHeaderWrapper>
);
}
export default MenuHeader;
추가로 getSegment 함수는 도메인의 string 값을 따오는 함수이다.
main 페이지와 calendar 페이지 2가지 경로가 존재하는데, 두 경로 모두 쿼리 스트링이 존재하지 않는다.
http://localhost:5173/main
위와 같이 단순한 경로이기 때문에, main 부분만 가져오는 함수를 구현해주었다.
이를 통해 현재 경로가 main인 경우 달력 버튼을, calendar 인 경우에는 홈 버튼을 렌더링하도록 구현하였다.
useState를 사용하지 않은 이유는 MenuHeader 라는 자식 컴포넌트에 Main 과 CalendarPage 라는 서로 다른 부모 컴포넌트가 존재하며 공통된 부모 컴포넌트는 존재하지 않기 때문에 상태값을 관리하기 어렵다고 판단하였기 때문이다.
728x90
'웹 > React' 카테고리의 다른 글
[React/리액트] TS 초기세팅 - tsconfig.json 주요 옵션들 및 tsconfig.node.json (1) | 2024.09.13 |
---|---|
[React/리액트] Vercel로 배포하기 (0) | 2024.09.13 |
[React/리액트] 퍼널(Funnel)구조로 연속되는 화면 구현하기 (2) | 2024.09.07 |
[React/리액트] TypeScript 에서 props 넘겨주기 (0) | 2024.09.05 |
[React/리액트] useReducer로 상태 관리하기 (1) | 2024.08.21 |