かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

React TypeScript 動的にタグを変えたい

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) しなくても済むし。  
 
おわり ₍ ᐢ•ᴗ•ᐢ ₎


[参考]

さよならポニーテール ホント好き