React.ComponentProops 모델 적극 활용

19794 단어 Reacttech
Atomic Design이 말하는 Atoms와 비슷한 일반 구성 요소에 대한 에피소드입니다.아래와 같이 프로포즈형 정의를 준비해 해설문을 자주 볼 수 있다.<input /> 라벨을 사용하지 않고 구성 요소화된 이유는 스타일을 실시하기 때문일 수 있지만 이 구성 요소가 받아들일 수 있는 Proops는 유한하고 유지 보수 원가가 높기 때문에 추천하지 않습니다.
Input.tsx
type Props = {
  value: string;
  onChange?: React.ChangeEventHandler<HTMLInputElement>
  onBlur?: React.FocusEventHandler<HTMLInputElement>
}
export const Input = ({ value, onChange, onBlur }: Props) => (
  <input
    value={value}
    onChange={onChange}
    onBlur={onBlur}
    className={styles.input}
   />
)

유지 관리 비용이 많이 드는 Atoms는?


유지보수 비용은 예를 들어 다시 주고 싶을 때onFocus 등 새로운 용례에 대응하는 수정 비용을 가리킨다.Input 어셈블리의 Proops에서 onFocus를 지정할 수 있도록 다음과 같이 수정해야 합니다.
Example.tsx
<Input
  value={value}
  onChange={onChange}
  onBlur={onBlur}
  onFocus={onFocus} // <- New
/>
Input.tsx
type Props = {
  value: string;
  onChange?: React.ChangeEventHandler<HTMLInputElement>
  onBlur?: React.FocusEventHandler<HTMLInputElement>
  onFocus?: React.FocusEventHandler<HTMLInputElement> // <- New
}
export const Input = ({ value, onChange, onBlur, onFocus }: Props) => (
  <input
    value={value}
    onChange={onChange}
    onBlur={onBlur}
    onFocus={onFocus} // <- New
    className={styles.input}
   />
)
Atoms는 일반적인 구성 요소 그룹으로 다양한 용례에 대응해야 한다.예를 들어 data-testidaria 속성 등은 장래에 필요할 것으로 예상된다.이 구성 요소에 대한 기대는 원래 <input /> 라벨에서만 스타일링을 실행합니다.

React.ComponentProops 모델 사용


이런 장면@types/react에는 ComponentProps의 유형 정의가 있는데 이걸 사용하세요.Generics에서 문자열 기능을 사용하여 태그 이름을 지정하면 허용 가능한 모든 Proops 유형을 찾을 수 있습니다.'본래의 라벨로 행동하고 싶은 구성 요소'라면 프로포즈의 유형 정의는 노력할 수 없다.
Input.tsx
type Props = React.ComponentProps<'input'> // <- here

export const Input = ({ value, onChange, onBlur, onFocus }: Props) => (
  <input
    value={value}
    onChange={onChange}
    onBlur={onBlur}
    onFocus={onFocus}
    className={styles.input}
   />
)

기간별 대입 사용


프롬프트를 하나하나 비추면 유지보수 비용은 큰 차이가 없다.<input /> 라벨이 받아들일 수 있는 모든 props는 모델을 지정할 수 있으며 그 다음에 분할 대입(Destructuring assignment)으로 모두 교부할 수 있습니다.이때 분할 대입도 포함className되지만 뒤에도 지정className={styles.input}되어 분할 대입으로 납부className되었기 때문에 무효가 되었다.
Input.tsx
type Props = React.ComponentProps<'input'>

export const Input = (props: Props) => (
  <input
    {...props} // <- props を全て渡す(onFocus や className も含まれる)
    className={styles.input} // <- こちらの指定が後勝ちになる
  />
)
props가 받아들인 className과 구성 요소가 주는 className이 공존하는 경우 clsx 등을 이용하여 스타일을 합성할 수 있습니다.이렇게 하면 스타일 수정의 여지를 조금 남길 수 있다.
Input.tsx
type Props = React.ComponentProps<'input'>

export const Input = ({ className, ...props }: Props) => (
  <input
    {...props} // <- className 以外、全ての props を分割代入
    className={clsx(className, styles.input)}
  />
)

Proops의 일부분만 빼고 싶어요.


반면'클라스네임을 받아들이고 싶지 않다·미세조정을 허용하고 싶지 않다'는 디자인 사상도 있다.이러한 설계의 경우 Type Script 표준으로 제공된 Omit형을 사용하십시오.Omit<T, 'className'>처럼 지정된 T에 정의된 속성 중 일부를 삭제할 수 있습니다.따라서 <Input /> 부품은 더 이상 부모가 지정하지 않는다className.
Input.tsx
type Props = Omit<React.ComponentProps<'input'>, 'className'>

export const Input = (props: Props) => (
  <input
    {...props} // <- className は含まれない(型エラーで事前に弾かれる)
    className={styles.input}
  />
)
부모가className을 지정할 수 있지만 적용되지 않는 설치를 방치하면 나중에 사용하는 사람들이 혼란스러울 수 있습니다.수령 거부를 명확히 표시하기 위해 친절하시겠죠.

Ref의 forwarding


이 의제에서 번거로운 것은ref의 인수인계이다.Function Component로 정의된 구성 요소는 ref 의 이름으로 전달할 수 없습니다. (별명이라면 가능합니다.)react-hook-form 등을 사용할 때ref를 교부하지 않으면 사용할 수 없습니다.이것은 아래의 방법에 따라 Ref의forwarding을 진행하면 됩니다(Generics의HTMLInputElement를 적당히 고쳐 주십시오)
Input.tsx
type Props = React.ComponentProps<'input'>

export const Input = React.forwardRef<HTMLInputElement, Props>(
  ({ className, ...props }, ref) => (
    <input {...props} ref={ref} className={styles.input} />
  )
);
https://ja.reactjs.org/docs/forwarding-refs.html
이상의 기술<input />은 모든 라벨의 원시적인 Propos를 계승할 수 있고<Input />는 모든 스타일의 구성 요소를 응용할 수 있다.이 밖에 React.ComponentProps<typeof Foo>에서 지정한 구성 요소Foo에 규정된 프로포즈를 직접 대여할 수 있다.편리한 타입이므로 구성 요소를 디자인할 때 활용해 보세요.

좋은 웹페이지 즐겨찾기