78
63

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 5 years have passed since last update.

【React+TypeScript】Functional Componentの定義方法

Last updated at Posted at 2019-03-07

React+TypeScript.png

React Hooksが来てから、ほとんどFunctional Componentを使うようになりました。

コーディングするときに、デフォルト引数指定やchildren指定はどうやるんだっけと、引っかかることがあったので備忘録として残すことにします。


まず、ヘッダ部分とプロパティの定義部分の例です。
プロパティの省略が出来ないPropsと、省略可能のプロパティがあるPropsOptionalを定義しています。

import React from "react";
import { storiesOf } from "@storybook/react";

const s = storiesOf("Functional Component", module);

// 省略不可
type Props = {
  x: number;
  y: number;
};

// 省略可能のプロパティあり
type PropsOptional = {
  x?: number;
  y: number;
};

コンポーネントの使用例の部分はStorybookを使ってます。
https://qiita.com/otanu/items/dd06d6702f673268c74e

引数をpropsで定義

基本パターン。

const Ex = (props: Props) => {
  return (
    <div>
      {props.x}:{props.y}
    </div>
  );
};
s.add("Ex", () => <Ex x={1} y={2} />);

引数をpropsで定義(省略可能)

プロパティを省略可能にするには、?をつけて定義すれば、x?: number | undefinedと定義したことになる。
プロパティを指定しなければundefinedが入るのでundefinedが入っても大丈夫なように処理をする必要がある。Object型のプロパティで、それのメソッドを呼び出す場合は、明示的にundefinedのチェックをしないとエラーになるので少し厄介。

type PropsOptional = {
  x?: number;
  y: number;
};

const ExOptional = (props: PropsOptional) => {
  return (
    <div>
      {props.x === undefined ? "なし" : props.x}:{props.y}
    </div>
  );
};

s.add("ExOptional", () => (
  <>
    <ExOptional y={2} />
    <ExOptional x={1} y={2} />
  </>
));

defaultPropsを定義すればデフォルト値の指定が出来る。このやり方だと、プロパティを省略可能ではないPropsで定義が出来るのでundefinedチェックが要らなくなる。

const ExOptional2 = (props: Props) => {
  return (
    <div>
      {props.x}:{props.y}
    </div>
  );
};
ExOptional2.defaultProps = {
  x: 1
};

s.add("ExOptional2", () => <ExOptional2 y={2} />);

型の定義だけを見れば、xが省略出来ないように見えるのが少し気持ち悪い気がする。
しかし、コンポーネントを使うときは、VSCodeの補完だとx?と表示されるし、処理の中ではundefinedにならないので、
こちらのPropsを使う方が正解な気がする?

引数ハッシュで定義

Functional Componentの定義方法として、props引数の定義ではなく、Hashで定義することも出来る。

const ExHash = ({ x, y }: Props) => {
  return (
    <div>
      {x}:{y}
    </div>
  );
};
s.add("ExHash", () => <ExHash x={1} y={2} />);

いちいちpropsを指定しなくてもプロパティにアクセス出来るのと、以下の用にデフォルト値を引数の中で指定できる所がメリットだと思う。

const ExHashOptional = ({ x = 10, y }: PropsOptional) => {
  return (
    <div>
      {x}:{y}
    </div>
  );
};
s.add("ExHashOptional", () => <ExHashOptional y={2} />);

プロパティをまとめて別のコンポーネントに渡したりする場合はprops引数を使用、簡単なコンポーネントの場合はHash指定という使い分けだろうか。

childrenプロパティを使用する場合

呼び出し元から子コンポーネントを渡す場合は、プロパティにchildrenプロパティを定義する。
childrenを省略可能にする場合は、children?と指定すればいい。

type PropsWithChild = {
  x?: number;
  y: number;
  children: React.ReactNode;
};

const ExWithChild = ({ x = 10, y, children }: PropsWithChild) => {
  return (
    <div>
      {x}:{y}
      {children}
    </div>
  );
};

s.add("ExWithChild", () => (
  <ExWithChild y={2}>
    <p></p>
  </ExWithChild>
));

FunctionComponentの型であるReact.FC(FunctionComponent)を使えば、わざわざchildrenを追加した型を定義しなくてもいい。(PropsOptionalが使える)

const ExWithChildFC: React.FC<PropsOptional> = ({ x = 10, y, children }) => {
  return (
    <div>
      {x}:{y + 1}
      {children}
    </div>
  );
};

s.add("ExWithChildFC", () => (
  <>
    <ExWithChildFC y={2} />
    <ExWithChildFC y={2}>
      <p></p>
    </ExWithChildFC>
  </>
));
78
63
1

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
78
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?