본문 바로가기
카테고리 없음

다른 형태 Header Compound Component 적용_02

by woody-j 2024. 1. 1.
"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;
  }