Chakra-UI にあるような as
props で動的にタグを変更できるコンポーネントを作りたかった
React.createElement を使う方法
import { createElement, FC, ReactNode } from 'react'; type HeadingProps = { as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; children: ReactNode; } export const Heading<HeadingProps> = ({ as: Heading = 'h1', children }) => { return createElement( Heading, { className: 'heading'}, children ); }
createElement
を使う場合、attribute は第二引数にオブジェクト渡せば良い。ただし拡張した特殊な attribute を使おうとすると上手く設定できない場合があるので注意が必要
ElementType を使う方法
as
で渡された文字列を ElementType
としてしまえば直接 JSX のタグとして扱える
import { ElementType, FC, ReactNode } from 'react'; type HeadingProps = { as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; children: ReactNode; } export const Heading<HeadingProps> = ({ as: tagStr = 'h1', children }) => { const Heading = tagStr as ElementType; return <Heading className="heading">{children}</Heading> }
props を ElementType 形にすればどんなタグでも可能にできる
import { ElementType, FC, ReactNode } from 'react'; type HeadingProps = { as?: ElementType; children: ReactNode; } export const Heading<HeadingProps> = ({ as: Heading = 'h1', children }) => { return <Heading className="heading">{children}</Heading> }
HTML タグとデザインを分離したいときはこの方法が良さそう。
as ElementType
(Type Assertion) しなくても済むし。
おわり ₍ ᐢ•ᴗ•ᐢ ₎
[参考]
さよならポニーテール ホント好き