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>
</>
));