프론트앤드/[React]

[TypeScript] 공통컴포넌트 Nav 이용해보기

헬리이 2023. 10. 24. 17:48
728x90
TS를 1도 모르는 상황에서 TS를쓰는 간단한 (?) 프로젝트가 시작되었다. 

 

오늘 구현 한 컴포넌트는 공통컴포넌트로, Nav.tsx이다. 

하나의 페이지에서 컴포넌트들만 바뀌는 식으로 개발을 할 것이었으며, 

그 중에서도 Contents 내에 title부분을 Nav.tsx(공통 컴포넌트)로 정하고  구현했다.

 

코드는 이렇다.

import React from 'react';

interface NavItem {
  title: string;
  subTitle?: string;
}

const SHAPE_NAV: NavItem = {
  title: 'What’s your nail shape?',
  subTitle: '(Choose based on the index finger.)',
};

const CONCERN_NAV: NavItem = {
  title: 'What kinds of nail concerns do you have?',
  subTitle: '* Multiple choices are allowed.',
};

//생략 (다른 카테고리 컴포넌트에 들어가야할 타이틀 및 서브타이틀)

export default function Nav({ navType }: { navType: string }) {
  const navList: Record<string, NavItem> = {
    shape: SHAPE_NAV,
    concern: CONCERN_NAV,
  //생략 
  };

  return (
    <nav className="w-screen min-h-65 max-h-10 text-center">
      <h1 className="text-4xl font-bold">{navList[navType].title}</h1>
      <p className="text-xl mt-3">{navList[navType].subTitle}</p>
    </nav>
  );
}

 

여기를 좀 더 설명하자면, 

 

- navType이라는 속성을 받아 특정 타입을 명시했다.  (이 타입은 문자열로 나타내며, 특정 항목을 나타낸다)

- navList 객체는 navType에 따라서 해당 항목을 선택하는 데 사용된다. (구조분해할당)

 

여기서 쓰인 Record를 따로 정리해 보겠다. 

같이 프론트엔드 하시는 분도 Record는 왜 사용하신거냐고 여쭤보셔서 검색을 해 보니, 

Record는 TypeScript에서 사용되는 제네릭 타입 중 하나로,  특정 객체 타입을 정의할 때 유용하게 사용되며, 일반적으로 Record는 객체의 키-값 쌍을 표현할 때 사용된다.

위의 코드에서 const navList: Record<string, NavItem>은

navList라는 객체가 문자열 키(string) 와 NavItem 타입의 값으로 이루어진 키-값 쌍을 포함하는 객체임을 정의하고 있다.

 

이 객체는 여러 종류의 nail 카테고리 title 및 subTitle 을 포함하고 있으며, 

각 키(key) 는 shape, concern, length 등을 나타내고, 각 값(value)은 NavItem 타입의 데이터를 가진다.

따라서 이렇게 정의된 navList 객체를 사용하면 shape, concern 등의 키에 해당하는 NavItem 데이터에 접근할 수 있고,이렇게 객체 타입을 정의함으로써 코드를 더 명확하게 작성할 수 있고, 타입 에러를 줄일 수 있습니다.

 

 

그리고 Nav.tsx에서 공통된 레이아웃 및 css를 적용하고, 

잘 적용이 되는지 확인을 하기 위해 Main.tsx에 props로 전달하여 값을 전달했다. 

 

//Main.tsx

import React from 'react';
import Nav from '../components/Nav';

export default function Main() {
  return (
    <div>
      <Nav navType="shape" />
    </div>
  );
}

깔끔해진 코드가 완성되었다.

 

 

728x90