카테고리 없음
다른 형태 Header Compound Component 적용_02
woody-j
2024. 1. 1. 13:20
"use client";
import { HeaderMap } from "@/types/header";
import { usePathname } from "next/navigation";
import React, { ReactNode } from "react";
import {
AlertHeader,
LogoHeader,
CloseHeader,
InteractiveHeader,
BackHeader,
BackCloseHeader,
} from "./TypeHeader";
// 헤더 유형별 컴포넌트 정의
const HeaderElement = {
Close: () => <CloseHeader />,
Back: () => <BackHeader />,
Home: () => <LogoHeader />,
BackClose: () => <BackCloseHeader />,
Alert: () => <AlertHeader />,
Interactive: () => <InteractiveHeader />,
Default: () => <div>default</div>,
};
// 현재 경로에 따른 헤더 컴포넌트 매핑
const headerMap: HeaderMap = {
"/반려정보1": HeaderElement.Close,
"/반려정보2": HeaderElement.Back,
"/login": HeaderElement.Home,
"/반려정보3": HeaderElement.BackClose,
"/": HeaderElement.Alert,
"/calender": HeaderElement.Interactive,
"/info": HeaderElement.Interactive,
"/myPage": HeaderElement.Interactive,
// 경로 추가
};
const HeadingComponent = () => {
return (
<Heading>
<Heading.Content />
</Heading>
);
};
const Heading = ({ children }: { children: ReactNode }) => {
return <header>{children}</header>;
};
const Content = () => {
const pathname = usePathname();
const HeaderComponent = headerMap[pathname] || HeaderElement.Default; // 경로에 해당하는 헤더 컴포넌트 또는 기본값
return <HeaderComponent />;
};
Heading.Content = Content;
export default HeadingComponent;
헤더 유형별 컴포넌트 정의
경로에 따라 어떤 헤더를 렌더링 할 지 결정
// 헤더 유형별 컴포넌트 정의
const HeaderElement = {
Close: () => <CloseHeader />,
Back: () => <BackHeader />,
Home: () => <LogoHeader />,
BackClose: () => <BackCloseHeader />,
Alert: () => <AlertHeader />,
Interactive: () => <InteractiveHeader />,
Default: () => <div>default</div>,
};
경로에 따른 헤더 매핑
해당 경로에 따라 컴포넌트를 가지고 옵니다.
// 현재 경로에 따른 헤더 컴포넌트 매핑
const headerMap: HeaderMap = {
"/반려정보1": HeaderElement.Close,
"/반려정보2": HeaderElement.Back,
"/login": HeaderElement.Home,
"/반려정보3": HeaderElement.BackClose,
"/": HeaderElement.Alert,
"/calender": HeaderElement.Interactive,
"/info": HeaderElement.Interactive,
"/myPage": HeaderElement.Interactive,
// 경로 추가
};
HeadingComponent 및 Heading
HeadingComponent는 최상위 커모넌트로 내부에서 heading을 사용합니다.
const HeadingComponent = () => {
return (
<Heading>
<Heading.Content />
</Heading>
);
};
const Heading = ({ children }: { children: ReactNode }) => {
return <header>{children}</header>;
};
CurrentPath로 컴포넌트 렌더링
headerMap에서 경로에 따라 설정한 컴포넌트를 렌더링합니다.
const Content = () => {
const pathname = usePathname();
const HeaderComponent = headerMap[pathname] || HeaderElement.Default; // 경로에 해당하는 헤더 컴포넌트 또는 기본값
return <HeaderComponent />;
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body className={pretendard.className}>
<RecoilRootWrapper>
<Container>
<HeadingComponent />
{children}
</Container>
</RecoilRootWrapper>
</body>
</html>
);
}
커스텀 유틸리티 클래스 생성
header component를 만들면서 css가 겹쳤다.
<header className="w-full md:max-w-3xl h-14 mx-auto px-2 py-1 flex items-center justify-between ">
//BackClose
export const BackCloseHeader = () => {
return (
<header className="w-full md:max-w-3xl h-14 mx-auto px-2 py-1 flex items-center justify-between">
<IconBtnWrapper onClick={() => {}}>
<IconLeft />
</IconBtnWrapper>
<IconBtnWrapper onClick={() => {}}>
<IconX />
</IconBtnWrapper>
</header>
);
};
//Alert
export const AlertHeader = () => {
return (
<header className="w-full md:max-w-3xl h-14 mx-auto px-2 py-1 flex items-center justify-between">
<Link href="/" className="px-3">
<Image src={logo.src} alt="Pet diary logo" width={75} height={18} />
</Link>
<IconBtnWrapper onClick={() => {}}>
<IconBell />
</IconBtnWrapper>
</header>
);
};
막상 부모에 넣어주자니 조금씩 css가 달라서 고민이 됐다.
const Heading = ({ children }: { children: ReactNode }) => {
return <header>{children}</header>;
};
고민하다 @apply 라는 것을 알게되었고 이것을 접목해보고자 했다.
하지만 @apply 는 공식에도 있듯이, tailwindCss의 핵심 가치에 이율배반적일 수 있다고 한다.
이럴 때는 사용하지말자.
깔끔해보이기 위해서.
이럴 때는 사용해라.
버튼 및 양식 컨트롤과 같이 매우 작고 재사용성이 높은 항목에 사용해라
//globals.css
.header {
@apply w-full md:max-w-3xl h-14 mx-auto px-2 py-1 flex items-center justify-between;
}