APPJAM]タイプスクリプトによる選択ボタン機能


YamatypescriptでどうやってそのChiprops typeを手に入れてselectボタンを自分で作ったのか...

selectボタンを直接作成


buttonラベルを使用してselectボタンを直接作成しています.必要なことは次のとおりです.

選択可能な条件(dropdown item)入力ボタン
上下切替アイコン(isOpenに依存)
dropdown itemを選択すると、ボタンが初期化されます.一度に1つのボタンだけを開く
Active効果:border,shadow dropdown item接続api を選択
カテゴリが選択されていない場合は、を無効にします.
総時間、価格、開設日、繰り返し視聴時間、質疑応答時間によって、ドロップダウンメニューごとに異なります.
<SortingBtn>총 소요시간</SortingBtn>
<SortingBtn>가격</SortingBtn>
<SortingBtn>...</SortingBtn>
<SortingBtn>총 소요시간</SortingBtn>
こうやっていちいち入れたかったのですが、下のdropdownメニューが出てくるのが違うので、ボタン標準と下のdropdownメニュー名をそれぞれ対象に管理することにしました.

SortingBox

return (
    <div>
      {sortingCriteria.map((criteria) => (
        <SortingBtn
          key={criteria}
          value={criteria}
          dropListName={dropListName}
          onClickOpenSorting={handleOpenSorting}
          isOpen={isOpen}
          onClickSortingItem={handleClickSortingItem}
          isSelected={isSelected}
          selectedItem={selectedItem}
          criteria={criteria}
        >
          {criteria}
        </SortingBtn>
      ))}
    </div>
  );
}

SortingBtn(各selectボタン)


interface SortingBtnProps {
  value: sortingType;
  children: React.ReactNode;
  dropListName: IDropListName;
  selectedItem: ISelectedItemName;
  isOpen: ISorting;
  isSelected: ISorting;
  onClickOpenSorting: (criterial: sortingType) => void;
  onClickSortingItem: (value: sortingType, item: string) => void;
  criteria: sortingType;
}

...

function SortingBtn({
  onClickOpenSorting,
  onClickSortingItem,
  isOpen,
  isSelected,
  dropListName,
  selectedItem,
  value,
  criteria,
}: SortingBtnProps) {
  return (
    <StyledRoot onClick={() => onClickOpenSorting(criteria)}>
      <BtnTextWrapper>
        <CriteriaItem color={colors.gray6}>{value}</CriteriaItem>
        {isSelected[value] && (
          <>
            <CriteriaItem>|</CriteriaItem>
            <CriteriaItem color={colors.mainBlue}>{selectedItem[value]}</CriteriaItem>
          </>
        )}
      </BtnTextWrapper>
      {isOpen[value] ? <ArrowUp /> : <ArrowDown />}
      {isOpen[value] && (
        <DropDownBox>
          {dropListName[value].map((item) => (
            <DropDownItem key={item} onClick={() => onClickSortingItem(value, item)}>
              {item}
            </DropDownItem>
          ))}
        </DropDownBox>
      )}
    </StyledRoot>
  );
}
  • isOpen:trueでArrow方向が変わりました.
  • 図は、
  • の各選択ボタンのドロップダウンメニューである.
  • onClickSortingItem関数は、value(選択された選択ボタンの名前)とitem(選択されたドロップダウンメニュー)を受信し、どのメニューをボタンに入れるかの情報を取得します.
  • 1.管理ドロップダウンリストオープン:isOpen

    //isOpen 객체의 type정의
    export interface ISorting {
      [key: string]: boolean;
    }

  • 1つのドロップダウンメニューが開いている場合、他のは閉じなければなりません.1回に複数を管理します.
    =>オブジェクトに「開くかどうか」(isOpen)ドロップダウンリストを入れます.ex){「定期視聴時間」:true,...}

  • isOpenオブジェクトを作成するには、forEach文をsortingCriteria配列として使用してfalseの値を持つオブジェクトを作成します.
    const sortingObject: ISorting = {};
    
    sortingCriteria.forEach((element) => (sortingObject[element] = false));
    
    const [isOpen, setIsOpen] = useState(sortingObject);
  • isOpen state로 관리한다.
    기본 값으로 들어가는 객체는 다음과 같다.
    
    {  "총 소요시간": false,
       "가격": false,
       "개설일": false,
       "반복시청 기간": false,
       "질의응답 시간": false,
     }
     
     
     
     
    const handleOpenSorting = (criteria: sortingType) => {
    switch (criteria) {
    case criteria:
    setIsOpen({
    ...sortingObject,
    [criteria]: !isOpen[criteria],
    });
    break;
    }
    };
    버튼 클릭 시, 버튼의 기준(sortingCriteria의 요소)을 가져와서 switch문에서 처리
    각각의 case마다 선택한 기준을 제외하곤 모두 false로 바꿔주고(sortingObject는 isOpen의 default값으로 들어간 객체임. 이걸 사용했음.)
    선택된기준을 key로 하는 value는 반대 값으로 바꿔준다.
    
    
    ### 2. 드랍다운 아이템 클릭시 값 넣기: selectedItem
    ### 3. 한 버튼만 셀렉트 할 수 있음 (중복 선택 불가): isSelected
    export type sortingType=「総所要時間」|「価格」|「開設日」|「定期視聴時間」|「質疑応答時間」;
    //dropdownドロップダウン・リスト・タイプの定義
    export type IDropListName = {
    [key in sortingType]: string[];
    };
    
    
    
    
    -> **모두 한 객체에 담아 관리하기**
    const isSelectedObject: ISorting = {};
    const selectedItemName: ISelectedItemName = {};
    sortingCriteria.forEach((element) => (isSelectedObject[element] = false));
    sortingCriteria.forEach((element) => (selectedItemName[element] = ""));
    const [isSelected, setIsSelected] = useState(isSelectedObject);
    const [selectedItem, setSelectedItem] = useState(selectedItemName);
    - 선택된 기준의 경우만 무엇이 선택되었는지 버튼 안에 표시되어야함.
    중복 선택이 안되기 때문에 isOpen처럼 isSelected도 객체로.. 한번에 관리한다.
    초기값은 모두 false.
    
    - 중복 정렬기능이 없기 때문에 한 곳에서 선택했으면 나머지는 초기화되어야함
    어떤 기준의 어떤 기준 목록을 선택했는지 저장 필요 ex){"가격": "높은 순", ...} 초기값은 모두 빈 문자열
    
    - isOpen과 같이 정렬 기준배열을 forEach문으로
    
    
    
    
    const handleClickSortingItem = (value: sortingType, item: string) => {
    switch (item) {
    case item:
    setSelectedItem({
    ...selectedItemName,
          [value]: item,
        });
        setIsSelected({
          ...isSelectedObject,
          [value]: true,
        });
        break;
    }
    };
    
    
    
    
    - 드랍다운 아이템을 클릭하면 어떤 기준을 선택했고, 그 기준(value)의 어떤 목록(item)을 선택했는지 받아온다.
    - item이 '긴 순서' '짧은 순서'로 겹치는 경우가 있긴 한데 받아오는 value가 달라서 잘 작동되는 것 같다.
    - 어떤 item이 선택되었는지 selectedItemd에 저장하고, 나머지는 빈 문자열로 초기화
    - 어떤 기준(value)이 선택되었는지 true로 바꾸고 나머진 false로 초기화
    
    
    
    
    typescript를 배운지 1개월도 되지 않은 상태로 프로젝트 진행중이라 얼렁뚱땅 한 것 같은데, 다행히 잘 돌아가는 걸 보면 이상은 없는 것 같다.
    
    앱잼이 끝나면 typescript개념을 다시 익히면서 차근차근 배우고 어떻게 효율적인 코드를 작성할 수 있을지 고민해보면 좋을 것 같다.