Polymorphic한 컴포넌트

Views:
7
Category:
Post
Posted on:
2024. 4. 25.

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>