React TypeScriptでのPropsの書き方について

## アジェンダ
React TypeScriptでのPropsの書き方について簡単にまとめます。
私が実際に実装で使用するのは、見出しの先頭に⭐️がついている方法になります。

## Propsの基本的な使い方
### コンポーネントにPropsを渡す
まずは、基本的な使い方から。
コンポーネントにデータを渡すとき、そのデータを属性として指定することで、コンポーネントに対して必要な情報を送ることができます。

```tsx
// 文字列の場合 ""
<Card1
  title="タイトル名"
  text="ここに本文が入ります"
/>;
// 文字列以外の場合 {}
<Card2
  number={数字}
  onClick={関数名}
/>;
```

このコードでは、Card1コンポーネントに`title`と`text`、Card2コンポーネントには`number`と`onClick`という自分で作った属性のようなものを使ってデータを渡しています。これらの属性のようなものをReactではPropsと呼びます。これを使えば、コンポーネントにも外からデータを渡して、動きや見た目をカスタマイズすることができます。

### コンポーネントでPropsを受け取る

ReactでPropsを受け取るには、いくつか方法があります。
一つは、Propsを一つのオブジェクトとして受け取る方法です。

#### オブジェクトで受け取る方法

```tsx:Card.tsx
import { FunctionComponent } from 'react';

type Props = {
  title: string;
  text: string;
};

export const Card: FunctionComponent<Props> = (props) => {
  return (
    <div className="card">
      <h1 className="card-title">{props.title}</h1>
      <p className="card-text">{props.text}</p>
    </div>
  );
}
```

この書き方で、Cardコンポーネントは、Propsをそのまま受け取ります。Propsのプロパティにアクセスするには、`props.title`や`props.text`のように`props`の後にドット( . )をつけて指定します。

#### ⭐️分割代入で受け取る方法
もう一つは、分割代入を使って、Propsから必要なデータだけを取り出す方法です。

```tsx:Card.tsx
import { FunctionComponent } from 'react';

type Props = {
  title: string;
  text: string;
};

export const Card: FunctionComponent<Props> = ({ title, text }: Props) => {
  return (
    <div className="card">
      <h1 className="card-title">{title}</h1>
      <p className="card-text">{text}</p>
    </div>
  );
}
```

この書き方で、Cardコンポーネントは`title`と`text`という2つのPropsを受け取っています。Propsの中から必要な値だけを取り出して、直接使うことができます。これを分割代入といいます。

どちらの書き方でもOKです。分割代入を使うと、`props.title`と書く代わりに、`title`と直接的に書けるからコードがスッキリするので、私は、分割代入のやり方を使用してます。

#### ⭐️デフォルトの値を設定する

Propsにデフォルト値を設定することもできます。これは、特定のPropが渡されなかった場合に備えて、あらかじめ値を設定しておく方法です。

```tsx:Card.tsx
import { FunctionComponent } from 'react';

type Props = {
  title?: string;
  text: string;
};

export const Card: FunctionComponent<Props> = ({ title = "タイトルなし", text }: CardProps) {
  return (
    <div className="card">
      <h1 className="card-title">{title}</h1>
      <p className="card-text">{text}</p>
    </div>
  );
}
```

このコードでは、`Card`コンポーネントが使われる時にもし`title`の値が指定されなかった場合、自動的に「タイトルなし」と表示されるように設定しています。

### コンポーネント同士を入れ子にする

Reactでは、コンポーネントを他のコンポーネント内に「入れ子」にすることで、同じコンポーネントをいろいろな場所で使い回したり、コードをすっきり整理したり、特定の機能をひとまとめにしたりするのに役立ちます。

#### ⭐️children を利用する

Reactコンポーネントを「入れ子」にする方法の一つは、「children」プロパティを利用することです。childrenとは特別なPropsで、コンポーネントのタグに挟まれた内容を指します。

```tsx:Card.tsx
import { FunctionComponent, ReactNode } from 'react';

type Props = {
  title: string;
  children: ReactNode;
};

export const Card: FunctionComponent<Props> = ({ title, children }: Props) => {
  return (
    <div className="card">
      <h1 className="card-title">{title}</h1>
      {children}
    </div>
  );
}
```

```tsx:App.tsx
import { Card } from "./Card";

export function App() {
  return (
    <div>
      <Card title="タイトル1">
        <p>ここに本文が入ります。</p>
        <CardImage
          src="https://sample-img.png"
          alt="サンプル画像"
        />
      </Card>
      <Card title="タイトル2">
        <p>ここに本文が入ります。</p>
        <CardImage
          src="https://sample-img.png"
          alt="サンプル画像"
        />
      </Card>
    </div>
  );
}
```

```tsx:Card.tsx
type Props = {
  src: string;
  alt: string;
};

export function CardImage({ src, alt }: Props) {
  return <img src={src} alt={alt} />;
}
```

このコードでは、`h2`や`p`タグ、さらには`CardImage`のような別のコンポーネントも含まれます。これらは、`Card`コンポーネントにchildrenとしてデータを渡します。