はじめに
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に置換すると良いでしょう。