はじめに
ReactにHooksが導入され、最近ではFunction Componentを採用することがほとんどになってきたように思います。
Function Componentを定義するための型としてReact.FC
が提供されているのですが、いくらかのデメリット(というより使う必要のなさ)があり、敢えて使っていないプロジェクトも数多く存在しています。
そんな中、デメリットを少し解消したReact.VFC
が生み出されていたため共有します。
React.FCとは
先述したとおりFunction Componentを定義するための型で、以下のように使用します。
interface Props {
hoge: string;
}
const Component: React.FC<Props> = (props) => {
return (
<div>
<p>{props.hoge}</p>
</div>
);
};
const Parent: React.FC = () => {
return (
<div>
<Component hoge="piyo" />
</div>
);
};
デメリットの一つとして、「children
(タグの間の要素)の有無がわからない」というものがあります。
React.FC
ではchildren
が最初から暗黙的に定義されてしまっているため、必要ないときに渡してしまってもエラーにならない仕様になっています。
interface Props {
hoge: string;
// childrenを定義していない
}
const Component: React.FC<Props> = (props) => {
// childrenは必要ない
return (
<div>
<p>{props.hoge}</p>
</div>
);
};
const Parent: React.FC = () => {
return (
<div>
{/* childrenがあるのにエラーが出ない */}
<Component hoge="piyo" >
children
</Component>
</div>
);
};
これではTypeScriptの良さが半減してしまいます。
React.VFCの登場
React.VFC
ではchildren
が含まれておらず、先程のように渡そうとするとエラーになります。
interface Props {
hoge: string;
// childrenを定義していない
}
// React.VFCに変更
const Component: React.VFC<Props> = (props) => {
// childrenは必要ない
return (
<div>
<p>{props.hoge}</p>
</div>
);
};
const Parent: React.VFC = () => {
return (
<div>
<Component hoge="piyo">
children
</Component>
{/* ERROR: Type '{ children: string; hoge: string; }' is not assignable to type 'IntrinsicAttributes & Props'.
Property 'children' does not exist on type 'IntrinsicAttributes & Props'.ts(2322) */}
</div>
);
};
children
が必要な場合は、以下のようにちゃんと明記してあげればOKです。
interface Props {
hoge: string;
children: React.ReactNode; // childrenを定義
}
const Component: React.VFC<Props> = (props) => {
return (
<div>
<p>{props.hoge}</p>
<p>{props.children}</p> {/* "children"と表示される */}
</div>
);
};
const Parent: React.VFC = () => {
return (
<div>
<Component hoge="piyo">
children
</Component>
</div>
);
};
React.VFC
を用いることにより、children
の有無がひと目で分かるようになりました!
React.FCの今後
React.VFC
の登場によってReact.FC
を使う理由がなくなってしまったのですが、このままReact.FC
をなくしていくわけではないようです。
むしろReactとしては、今後もReact.FC
を主流として扱っていくようです。
というのも、React.FC
にchildren
が含まれないべきだという考え方はもとから存在しており、@types/react 18
からは含まれなくなる予定です。
これは破壊的な変更であることから、移行措置として導入されたものが今回のReact.VFC
であるようです。
これからの開発では、一旦すべてReact.VFC
で定義し、必要に応じてchildren
を定義するようにしましょう。
@types/react 18
がリリースされればどちらも同じものになる(はず)なので、その際にReact.VFC
をReact.FC
に置換すると良いでしょう。