React FCの型についての話。

Reactでコンポーネントを書くとき、

type Props = { title: string }

const App: React.FC<Props> = ({ children, ...props }) => {
 return (
   <>
    <p>{props.title}</p>
    {children}
   </>
 )
}

上記のようにFunction Componentで型はReact.FC、ジェネリクスで別途定義したPropsの型を渡す〜っていうのがよく見る書き方だと思ってる。

ただ、最近React.FCを使わないという記事が目に入るようになった。

どうやらReact.FCだと暗黙的にchildrenを受け取ってしまっているので、必要不必要関係なしに渡せる受け取れるのが問題らしい。

代わりにReact.VFCというchildrenが定義されてない型を使うことを推奨してる人が多い。VはvoidのV。

ちなみに手元にあった @types/react v17.0.4時点でのReact.FCの型定義は下記。

type FC<P = {}> = FunctionComponent<P>;

interface FunctionComponent<P = {}> {
  (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
  propTypes?: WeakValidationMap<P>;
  contextTypes?: ValidationMap<any>;
  defaultProps?: Partial<P>;
  displayName?: string;
}

type PropsWithChildren<P> = P & { children?: ReactNode };

childrenが暗黙的にReactNodeで定義してある。

VFCはこんな感じ。

type VFC<P = {}> = VoidFunctionComponent<P>;

interface VoidFunctionComponent<P = {}> {
  (props: P, context?: any): ReactElement<any, any> | null;
  propTypes?: WeakValidationMap<P>;
  contextTypes?: ValidationMap<any>;
  defaultProps?: Partial<P>;
  displayName?: string;
}

propsがPropsWithChildrenでないこと以外同じっぽい。

つまりVFCで冒頭のコードを書く際はこうなる。

type Props = {
  title: string
  children: ReactNode // 使うときだけ定義
}

const App: React.VFC<Props> = ({ children, ...props }) => {
 return (
   <>
    <p>{props.title}</p>
    {children}
   </>
 )
}

ただ、将来的にはFCからも暗黙的にchildrenが定義されなくなるらしい。

個人的なまとめ

正直FCで定義されてるchildrenってoptionalだし…FC→VFCにしてバージョンアップのタイミングでVFC→FCに置き換えるコストを考えると、「FCのままchildrenを使うパターンのみ定義」が一番カロリー少なくていいかなと思ったり(諸説あり)

参考にさせていただいた記事。


この記事が気に入ったらサポートをしてみませんか?