React.ComponentProops 모델 적극 활용
<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.tsxtype 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-testid
와 aria
속성 등은 장래에 필요할 것으로 예상된다.이 구성 요소에 대한 기대는 원래 <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} />
)
);
이상의 기술
<input />
은 모든 라벨의 원시적인 Propos를 계승할 수 있고<Input />
는 모든 스타일의 구성 요소를 응용할 수 있다.이 밖에 React.ComponentProps<typeof Foo>
에서 지정한 구성 요소Foo
에 규정된 프로포즈를 직접 대여할 수 있다.편리한 타입이므로 구성 요소를 디자인할 때 활용해 보세요.
Reference
이 문제에 관하여(React.ComponentProops 모델 적극 활용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/takepepe/articles/atoms-type-definitions텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)