StudyForYou / ouahhan-typescript-with-react

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

#23 [8장_1] 제시된 Button 컴포넌트가 button 태그의 기본 어트리뷰트와 ref도 props로 받을 수 있도록 확장해 주세요! #36

Closed hyeyoonS closed 2 months ago

hyeyoonS commented 2 months ago

❓문제

import React from 'react'

type ButtonProps = {
  onClick: () => void;
  children: React.ReactNode;
}

const Button = ({ onClick, children }: ButtonProps) => {
  return (
    <button onClick={onClick}>
      {children}
    </button>
  )
}

export default Button

🎯답변

drizzle96 commented 2 months ago

button 태그의 기본 어트리뷰트를 props로 받기 위해서는 React.ComponentPropsWithoutRef를 사용할 수 있고, ref를 props로 받기 위해서 forwardRef와 제네릭을 사용할 수 있습니다.

import React, { forwardRef } from 'react'

type ButtonProps = {
} & React.ComponentPropsWithoutRef<'button'>

const Button = forwardRef<HTMLButtonElement, ButtonProps>(({ children, ...buttonProps }, ref) => {
  return (
    <button ref={ref} {...buttonProps}>
      {children}
    </button>
  )
})

Button.displayName = 'Button'
export default Button
summerkimm commented 2 months ago
import React, { forwardRef } from 'react'

type NativeButtonType = React.ComponentPropsWithoutRef<"button">;

type ButtonProps = {
  children: React.ReactNode;
} & NativeButtonType;

const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
  const { children, onClick, ...buttonProps } = props;
  return (
    <button ref={ref} onClick={onClick} {...buttonProps}>
      {children}
    </button>
  )
})

export default Button;
hyeyoonS commented 2 months ago
  1. 기존의 ButtonProps의 type에 ButtonHTMLAttributes<HTMLButtonElement>를 추가합니다. → button 태그의 기본 Attribute를 받을 수 있습니다.

2.forwardRef를 사용하여 ref를 전달합니다. → ref를 props로 받을 수 있습니다.

import React, { forwardRef } from 'react'

type ButtonProps = {
  onClick: () => void;
  children: React.ReactNode;
} & React.ComponentPropsWithoutRef<'button'>

const Button = forwardRef<HTMLButtonElement, ButtonProps>(({ onClick, children }, ref) => {
  return (
    <button onClick={onClick} ref={ref}>
      {children}
    </button>
  );
});

export default Button;