propsでタグとなる文字列をpropsで渡して、HTMLタグとしてレンダリングするコンポーネントの作り方を紹介します。
TypeScriptやReactを学び始めて間もない方にオススメの内容だと思っております!
【結論】利用したいタグを直接渡せるようにする
私のような初心者はコンポーネントを作成する時に下記のような作り方をしてしまいます。
import React, { FC } from 'react';
type Props = {
ordered?: boolean;
};
const List: FC<Props> = ({ ordered }) => {
const ListTag = ordered ? 'ol' : 'ul';
return (
<ListTag>
<li>listItem</li>
<li>listItem</li>
</ListTag>
);
};
export default List;
別に悪くないとは思いますが…微妙だと思う点が2点あります。
- orderedという余計なpropsを増やしてしまっている
- 変数に入れるワンクッションが少し煩わしく感じる
今の仕様だとulと
ol`どちらかしか入らないにもかかわらず、orderedというpropsを必要とすることを知らないと使えないコンポーネントとなってしまっているのがスマートではありません…。
下記のようにコードを修正してみます。
import React, { FC } from 'react';
type Props = {
as: 'ul' | 'ol';
};
const List: FC<Props> = ({ as: Tag }) => {
return (
<Tag>
<li>listItem</li>
<li>listItem</li>
</Tag>
);
};
export default List;
asというpropsを定義し、ulとolが必ず入るようにリテラル型にしました。
さらにpropsで渡された値をTag
に代入して利用できる形にしました。
asを必須の値と設定していますが「?」をつけることで任意の値とした上で、propsにデフォルトの値を設定することも可能です!
type Props = {
as?: 'ul' | 'ol';
};
const List: FC<Props> = ({ as: Tag = 'ul' }) => {
asってなんだ?
asプロパティは、ReactのコンポーネントがレンダリングするHTMLタグを指定するためのものです。
なので先ほどのpropsのtype定義をstring
に変更するとエラーになります。
type Props = {
- as?: 'ul' | 'ol';
+ as?: string
};
// エラー内容
'Tag' を JSX コンポーネントとして使用することはできません
Its type 'string | undefined' is not a valid JSX element type.
型 'undefined' を型 'ElementType' に割り当てることはできません
HTMLタグの名前しか受け取れないはずのasプロパティに対してstring、任意の文字列を許容する形式に変えたことでHTMLタグとして認知できない文字列を渡せてしまうためエラーとなります。
【propsでタグとなる文字列を受け渡して動的にHTMLタグを生成するコンポーネントを作り方】まとめ
propsでタグとなる文字を受け渡す場合はasプロパティを使うことで安全なコンポーネントかつシンプルな記述を実現できます!
コンポーネントの性質によりますが、実装方法として覚えておくと便利だと思います!