252
132

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【TypeScript】React.VFCとは何ぞや

Last updated at Posted at 2021-03-03

はじめに

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

252
132
0

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
  3. You can use dark theme
What you can do with signing up
252
132

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?