search
LoginSignup
127

More than 1 year has passed since last update.

posted at

updated at

【TypeScript】React.VFCとは何ぞや

はじめに

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.FCchildrenが含まれないべきだという考え方はもとから存在しており、@types/react 18からは含まれなくなる予定です。
これは破壊的な変更であることから、移行措置として導入されたものが今回のReact.VFCであるようです。

これからの開発では、一旦すべてReact.VFCで定義し、必要に応じてchildrenを定義するようにしましょう。
@types/react 18がリリースされればどちらも同じものになる(はず)なので、その際にReact.VFCReact.FCに置換すると良いでしょう。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
127