[React + Typescript] 제네릭 컴포넌트

thousand_yj·2023년 7월 17일
0

Willing 프로젝트

목록 보기
10/18

현재 개발 중인 프로젝트에서 dropdown 요소가 재사용이 가능해보여서 시도해보고 있다. 다만 얽힌 요소가 꽤 있어서 열심히 고쳐보고 있다.

제네릭 사용 이유

드롭다운 요소에 전달되는 데이터는 IGroup / IColor 중 하나이다.

export interface IGroup {
  id: number;
  title: string;
  color: string;
}

export interface IColor {
  id: number;
  color: string;
}

그래서 드롭다운 요소가 둘 중 하나의 데이터를 전달받을 수 있게 설정하고, 데이터가 존재하면 로딩하고 아니면 비워두는 컴포넌트를 작성했다.

import { styled } from "styled-components";

interface DropdownAttrs {
  id: number;
  title?: string;
  color: string;
}

interface DropdownProps<T> {
  isUlVisible: boolean;
  setIsUlVisible: (x: boolean) => void;
  liClickHandler: (event: React.MouseEvent<HTMLElement>) => void;
  dataArray: T[];
}

function Dropdown<T extends DropdownAttrs>(props: DropdownProps<T>) {
  return (
    <Ul visible={props.isUlVisible}>
      {props.dataArray.map((data) => (
        <Li
          key={data.id}
          id={data.id.toString()}
          onClick={props.liClickHandler}
        >
          <ColorCircle colorstring={data.color} />
          {data.title}
        </Li>
      ))}
    </Ul>
  );
}

export default Dropdown;

const Ul = styled.ul<{ visible: boolean }>`
  display: ${(props) => (props.visible ? "block" : "none")};
  list-style: none;
  padding: 4px;
  position: absolute;
  border-radius: 4px;
  background-color: #ffffff;
  box-shadow: 0px 8px 8px 0px rgba(29, 91, 132, 0.25);
  max-width: 160px;
`;

const ColorCircle = styled.div<{ colorstring: string }>`
  min-width: 10px;
  min-height: 10px;
  border-radius: 50%;
  background-color: ${(props) => props.colorstring};
  margin: 0 11px 0 5px;
`;

const Li = styled.li`
  display: flex;
  align-items: baseline;
  cursor: pointer;
  &:hover {
    background-color: #cae2fe9c;
  }
  padding: 3px 5px;
  border-radius: 4px;
`;
profile
함께 일하고 싶은 개발자가 되기 위해 노력합니다. 코딩테스트 관련 공부 및 이야기는 티스토리에도 업로드되어 있습니다.

0개의 댓글