문자열과 onClick 함수를 props로 전달받는 Button 컴포넌트를 만든다고 가정하면 아래와 같은 컴포넌트를 만들어 쓸 수 있습니다.
interface ButtonProps {
children: string;
onClick: () => void;
}
const Button = ({ children, onClick }: ButtonProps) => {
return <button onClick={onClick}>{children}</button>;
};
export default Button;
그리고 아래와 같이 불러다 쓸 수 있겠죠?
import Button from "components/Button";
const App = () => {
return <Button onClick={() => console.log("Button Clicked")}>Button</Button>;
};
export default App;
하지만 button이라는 html tag에는 onClick이라는 prop이 이미 존재하고, 그 외 다양한 prop도 있습니다.
onClick 외에도 다양한 이벤트 핸들러 prop도 존재하고, style prop을 통해 인라인 스타일을 지정할 수도 있죠.
button 태그의 기본 props들을 확장하여 버튼 컴포넌트를 만들 수 있다면 좀 더 범용성이 넓은 컴포넌트를 만들 수 있지 않을까요?
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
const Button = (props: ButtonProps) => {
return <button {...props} />;
};
export default Button;
위 코드처럼 컴포넌트를 만들어 준다면,
button 태그의 기본적인 props들은 물론이고,
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
additionalProps: string;
}
const Button = (props: ButtonProps) => {
console.log(props.additionalProps);
return <button {...props} />;
};
export default Button;
추가적으로 필요한 props들을 받을 수 있게 됩니다.
import Button from "components/Button";
const App = () => {
return (
<Button additionalProps="Hello World" onClick={() => console.log("Button Clicked")}>
Button
</Button>
);
};
export default App;
저는 현재 프로젝트에서 emotion을 자주 사용 중인데, emotion을 쓰는 경우
상속받을 부모를 React.ButtonHTMLAttributes<HTMLButtonElement> 대신,
DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> 로 바꿔주시면 됩니다.
import { ButtonHTMLAttributes, DetailedHTMLProps } from "react";
import * as Style from "./style";
export interface ButtonProps
extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
width: number;
}
const Button = (props: ButtonProps) => {
return <Style.Button {...props} />;
};
export default Button;
import styled from "@emotion/styled";
import { ButtonProps } from "components/common/Button";
export const Button = styled.button<ButtonProps>`
width: ${({ width }) => `${width}rem`};
`;
import Button from "components/Button";
const App = () => {
return (
<Button width={100} onClick={() => console.log("Button Clicked")}>
Button
</Button>
);
};
export default App;
물론, 딱 필요한 props만을 받기 위해 html 태그의 기본 props들을 상속받지 말아야 할 경우도 있겠지만,
Button, Input과 같이 간단한 컴포넌트의 경우 일일이 interface와 type을 작성하는 시간을 줄여주고, 확장성이 좋아
컴포넌트 유지 보수에 리소스가 줄어들었습니다.
'웹 > 프론트엔드' 카테고리의 다른 글
[React] 재귀적인 구조에서 검색기능 구현하기 (0) | 2022.08.15 |
---|---|
[Next.js] Next.js에서 API Routes + TypeORM 사용하기 (1) | 2022.07.17 |
[React/Typescript] 리액트 컴포넌트 npm 라이브러리로 배포하기 (2) | 2022.07.03 |
반응형 CSS, 뷰포트, 여러 단위(%, vw, em, rem), 미디어 쿼리 (0) | 2022.04.02 |
[React] 이미지 모달 구현하기 (0) | 2021.10.21 |
댓글