Polymorphic한 컴포넌트
Polymorphic한 컴포넌트에 대하여
평소 스타일링은 css-in-js 방식을 선호한다.
그 중에서도 styled-components를 자주 사용했었는데
이번에 emotion을 사용해 보았는데, props로 as라는 속성에
html tag이름을 넣으면 tag가 바뀌게 되는 신기한 경험을 하였다.
import { Button } from "@shared/Button";
const App = () => {
return (
<div>
<Button as="a" href="https://example.com"/>
</div>
)
}
/* 위와 같이 버튼 컴포넌트에 as 속성과 href 속성을 넣게되면 */
/* a 태그와 같이 작동 한다 */
export default App;
신기 하지 않은가....만들어 보자...
import {
forwardRef,
ElementType,
ComponentPropsWithoutRef,
ComponentPropsWithRef,
ReactNode
} from 'react';
type ChameleonProps<T extends ElementType> = {
as?: T;
} & ComponentPropsWithoutRef<T>;
type ChameleonComponent = <U extends ElementType = 'div'>(
props: ChameleonProps<U> & { ref?: ComponentPropsWithRef<U>['ref'] }
) => ReactNode | null;
const Chameleon: ChameleonComponent = forwardRef(
<T extends ElementType = 'div'>(
{ as, ...props }: ChameleonProps<T>,
ref: ComponentPropsWithRef<T>['ref']
) => {
const Element = as || 'div';
return <Element {...props} ref={ref} />;
}
);
export default Chameleon;
Props의 타입을 선언해 주고, 다형성을 가질 컴포넌트 자체 함수의 타입도
선언해 줘야 한다고 한다.
그리고 참조한 글에서는 함수타입 정의에서 리턴되는 값이
() => ReactElement | null 이었는데 에러가 발생하여
() => ReactNode | null로 바꿔 주니 에러가 잡혔다.
오늘도 새롭고 즐겁게 하나 배웠다...
# Polymorphic한 컴포넌트에 대하여 평소 스타일링은 css-in-js 방식을 선호한다. 그 중에서도 styled-components를 자주 사용했었는데 이번에 emotion을 사용해 보았는데, props로 as라는 속성에 html tag이름을 넣으면 tag가 바뀌게 되는 신기한 경험을 하였다. ```js import { Button } from "@shared/Button"; const App = () => { return ( <div> <Button as="a" href="https://example.com"/> </div> ) } /* 위와 같이 버튼 컴포넌트에 as 속성과 href 속성을 넣게되면 */ /* a 태그와 같이 작동 한다 */ export default App; ``` 신기 하지 않은가....만들어 보자... ```js import { forwardRef, ElementType, ComponentPropsWithoutRef, ComponentPropsWithRef, ReactNode } from 'react'; type ChameleonProps<T extends ElementType> = { as?: T; } & ComponentPropsWithoutRef<T>; type ChameleonComponent = <U extends ElementType = 'div'>( props: ChameleonProps<U> & { ref?: ComponentPropsWithRef<U>['ref'] } ) => ReactNode | null; const Chameleon: ChameleonComponent = forwardRef( <T extends ElementType = 'div'>( { as, ...props }: ChameleonProps<T>, ref: ComponentPropsWithRef<T>['ref'] ) => { const Element = as || 'div'; return <Element {...props} ref={ref} />; } ); export default Chameleon; ``` Props의 타입을 선언해 주고, 다형성을 가질 컴포넌트 자체 함수의 타입도 선언해 줘야 한다고 한다. 그리고 참조한 글에서는 함수타입 정의에서 리턴되는 값이 () => ReactElement | null 이었는데 에러가 발생하여 () => ReactNode | null로 바꿔 주니 에러가 잡혔다. 오늘도 새롭고 즐겁게 하나 배웠다... <a href="https://kciter.so/posts/polymorphic-react-component/" target="_blank">[참조]</a>