StudyForYou / ouahhan-typescript-with-react

우아한 타입스크립트 with 리액트 스터디 레포 🧵
4 stars 0 forks source link

#24 [8장_2] JSX 문법으로 작성된 다음 Select 컴포넌트에 타입스크립트를 적용하고,어떤 부분에 타입스크립트를 적용했는지 말해주세요. #35

Closed hyeyoonS closed 2 months ago

hyeyoonS commented 2 months ago

❓문제

const Select = ({ onChange, options, selectedOption }) => {
  const handleChange = (e) => {
    const selected = Object.entries(options).find(
      ([_, value]) => value === e.target.value
    )?.[0];
    onChange?.(selected);
  };

  return (
    <select
      onChange={handleChange}
      value={selectedOption && options[selectedOption]}
    >
      {Object.entries(options).map(([key, value]) => (
        <option key={key} value={value}>
          {value}
        </option>
      ))}
    </select>
  );
};

🎯답변

drizzle96 commented 2 months ago
// 1. 컴포넌트 Props 타입을 생성하고 컴포넌트의 props 타입으로 지정한다.
// 2-1. onChange의 selected 인자와 selectedOption은 options 객체의 키 값으로 제한되어야 한다. 따라서 OptionType 제네릭을 선언한다.
// 2-2. 각 prop의 타입을 OptionType을 활용하여 정의한다.
// 2-3. 이 때 OptionType은 string: string 형태의 객체가 와야 하므로 Record<string, string>으로 제한한다.
type SelectProps<OptionType extends Record<string, string>> = {
  onChange?: (selected?: keyof OptionType) => void
  options: OptionType
  selectedOption?: keyof OptionType
}

// 2-4. 컴포넌트 사용처부터 OptionType을 넘겨줄 수 있도록 컴포넌트에도 같은 제네릭을 선언하고 컴포넌트 Props에 제네릭을 넘겨준다.
const Select = <OptionType extends Record<string, string>>({ onChange, options, selectedOption }: SelectProps<OptionType>) => {
  // 3. 리액트 이벤트 핸들러 타입을 이벤트 핸들러 함수의 타입으로 선언한다. (이벤트에 리액트 이벤트 타입을 선언할 수도 있음)
  const handleChange: React.ChangeEventHandler<HTMLSelectElement> = (e) => {
    const selected = Object.entries(options).find(
      ([_, value]) => value === e.target.value,
    )?.[0]
    onChange?.(selected)
  }

  return (
    <select
      onChange={handleChange}
      value={selectedOption && options[selectedOption]}
    >
      {Object.entries(options).map(([key, value]) => (
        <option key={key} value={value}>
          {value}
        </option>
      ))}
    </select>
  )
}
hyeyoonS commented 2 months ago

타입을 지정한 부분

handleChange 함수

Select 컴포넌트가 받는 props



interface SelectProps {
    onChange : (selectedKey: string | undefined) => void;
    options: { [key: string]: string };
    selectedOption: string | undefined;
}

const Select:React.FC<SelectProps> = ({ onChange, options, selectedOption }) => {
  const handleChange: React.ChangeEventHandler<HTMLSelectElement> = (e) => {
    const selected = Object.entries(options).find(
      ([_, value]) => value === e.target.value
    )?.[0];
    onChange?.(selected);
  };

  return (
    <select
      onChange={handleChange}
      value={selectedOption && options[selectedOption]}
    >
      {Object.entries(options).map(([key, value]) => (
        <option key={key} value={value}>
          {value}
        </option>
      ))}
    </select>
  )
};

앗...제 코드에서 더 발전한 게 연우님 코드 같네요...!?!?! 공부공부,,,,