中に <div> を入れられる <p> タグっぽい見た目コンポーネントを自作する
<p> の中に <div> を入れようとすると以下のようなエラーになってしまいます。
Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>
しかし、div なんていうのは React のあらゆるところで使われていて、これは p タグが使えないと言うのとほとんど変わりません。(もちろん、使わなければ良いのですが。)
では、中に <div> を入れられる <p> タグを作るにはどうすれば良いでしょうか。要するに margin-bottom が 1rem のブロック要素を作れば良いだけの話です。
src/components/P.tsx
interface Props extends React.HTMLAttributes<HTMLDivElement> {
// some other props
}
// <p> タグの代わりの <P> コンポーネント
export default function P({ children, style, ...props }: Props):
// style に marginBottom を追加する。
// ただし、marginBottom が既に指定されていた場合は上書きしない。
// また、style が undefined の場合は何も起きない。
const styleWithMarginBottom = { marginBottom: '1rem', ...style };
// children は div の子要素として渡す。
// 残りの props は div タグにそのまま渡す。
return (
<div style={styleWithMarginBottom} {...props}>
{children}
</div>
);
}
src/main.tsx
<P>
<div>Hello!</div>
</P>
これで入れられるようになりました。多分バッドプラクティスだと思うので会社では真似しないでください :-P
直接 style= 指定することを避けたい場合
直接 style= でスタイルを指定することを避けたい場合は、style を className に置き換えてください。ただし、CSS 適用の優先順位に注意してください。
参考
props の型には React.HTMLAttributes や ComponentProps を使用してください。
React.ComponentPropsを使ったコンポーネントの Props 設計
https://zenn.dev/tm35/articles/4bc94d7e6cb314