TypeScript+Reactでの関数コンポーネントとクラスコンポーネント(転何知人T+Rその4)

# [前回](https://qiita.com/botanic7arc/items/4398b2d49ef44f2073d8)までの状態

別ファイルの関数コンポーネントを呼び出した。

# 今回の目的

クラスコンポーネントと関数コンポーネントについて学習する。

# コンポーネントについて

Reactで使用できるコンポーネントには以下の2種類記述方法がある。

- 関数コンポーネント
- クラスコンポーネント

どちらとも名前の通り、関数コンポーネントは関数の書き方、クラスコンポーネントはクラスの書き方で記述する。

## 関数コンポーネント

### 手順

前回app.tsxに作成したPrintHelloWorldは関数コンポーネントである。

``` tsx
const PrintHelloWorld =()=> {
    return (
        <h1>Hello, world!</h1>
    );
}
```

関数であるため、入力を受け取ることが可能。
app.tsxのPrintHelloWorldを以下のように変更する。

``` tsx
//変更開始
const PrintHello = ({ name }:{name:string}) => {
//変更終了
    return (
        //変更開始
        <h1>Hello, {name}!</h1>
        //変更終了
    );
}
//変更開始
export { PrintHello };
//変更終了
```

index.tsxを以下のように変更する。

``` tsx
import React from 'react';
import ReactDOM from 'react-dom';
//変更開始
import {PrintHello} from './app';
//変更終了

ReactDOM.render(  
  <React.StrictMode>
    {/* 変更開始 */}
    <PrintHello name='Taro'/>
    {/* 変更終了 */}
  </React.StrictMode>,
  document.getElementById('root')
);
```

プログラム実行後、以下のように"Hello, Taro!"と表示されたら成功。

![スクリーンショット 2021-07-13 154242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/792099/d2d8a75d-4b65-c1dc-588a-09a842510633.png)


### 解説

#### app.tsx

``` tsx
const PrintHello = ({ name }:{name:string}) => {}
```

関数コンポーネントで入力をとるように変更している。
Reactのコンポーネントにおける入力は一般的に“props”と呼ばれる。
関数頭のかっこ内は{引数変数名}:{引数変数名:型}となる。
また、変数でこんにちはする相手が変わるのでコンポーネント名を"PrintHello"に変更している。

``` tsx
<h1>Hello, {name}!</h1>
``` 

変数を使用した文を返すように変更している。

``` tsx
export { PrintHello };
```

コンポーネント名を変更したためによるexport文の変更。

``` tsx
import {PrintHello} from './app';
``` 
コンポーネント名を変更したためによるimport文の変更。

``` tsx
<PrintHello name='Taro'/>
``` 
コンポーネントにname='Taro'を引数として受け渡している。記述方法は<関数コンポーネント名 引数名=内容/>となる。

### 引数を複数にするには

app.tsxのPrintHelloを以下のように変更する。

``` tsx
const PrintHello = ({ name, name2 }: { name: string, name2: string}) => {
    return (
        <h1>Hello, {name},{name2}!</h1>
    );
}
```

またindex.tsxのPrintHelloWorldを以下のように変更すると、引数が2つの関数コンポーネントを宣言、使用できる。

``` tsx
<PrintHello name='Taro' name2='Jiro'/>
``` 

![スクリーンショット 2021-07-13 160558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/792099/93858553-8615-a9f1-a9d2-7b9a1f2ec037.png)

## クラスコンポーネント

### 手順

app.tsxに以下Nowクラスコンポーネントを追加する。(PrintHelloコンポーネントは引数が2つの場合のものに変更している)

``` tsx
//追加開始
import React from 'react';
//追加終了

const PrintHello = ({ name, name2 }: { name: string, name2: string }) => {
    return (
        <h1>Hello, {name},{name2}!</h1>
    );
}
export { PrintHello };

//追加開始
class Now extends React.Component {
    constructor(props: any) {
        super(props);
        this.state = new Date();
    }

    render() {
        return (
            <div>
                <h2>{String(this.state)}</h2>
            </div>
        )
    }
}

export { Now };
//追加終了
``` 

index.tsxは以下のように変更する。

``` tsx
import React from 'react';
import ReactDOM from 'react-dom';
import {PrintHello} from './app';
//追加開始
import {Now} from './app';
//追加終了

ReactDOM.render(
  <React.StrictMode>
    <PrintHello name='Taro' name2='Jiro'/>
    {/* 追加開始 */}
    <Now />
    {/* 追加終了 */}
  </React.StrictMode>,
  document.getElementById('root')
);
``` 

下のように現在日時が追加で表示されていたら成功。

![スクリーンショット 2021-07-14 134059.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/792099/41fc6c9b-741a-88da-e10b-a2c2ba80be59.png)


### 解説

#### app.tsx

``` tsx
import React from 'react';
``` 
クラスコンポーネントは、React.Componentクラスを継承して作成するため、reactをインポートする。

``` tsx
//追加開始
class Now extends React.Component {
    constructor(props: any) {
        super(props);
        this.state = new Date();
    }

    render() {
        return (
            <div>
                <h2>{String(this.state)}</h2>
            </div>
        )
    }
}

export { Now };
//追加終了
``` 

クラスコンポーネント。通常のクラスと同様にコンストラクタを作成できる。関数コンポーネントと同様にprops(入力)を扱うことができる。
クラスコンポーネントは関数コンポーネントと違い、このNowクラスではコンストラクターでstateに現在日時を格納している。
描画内容はrender関数を使用して返却する。

#### index.tsx

関数コンポーネント追加時と同様のことをしているため省略。

# 要約

Reactで使用できるコンポーネントには以下の2種類がある。

- 関数コンポーネント
- クラスコンポーネント

関数コンポーネント、クラスコンポーネントともにprops(入力)を受け取ることができる。クラスコンポーネントはstateというオブジェクトを使用して、情報を保持することができる。

# 次

[React HooksとuseState](https://qiita.com/botanic7arc/items/9e1ec00496559142fd2c)

# 派生記事
- [props宣言とtypeの型定義を使わずに関数コンポーネントの引数の型を指定する(TypeScript) - Qiita](https://qiita.com/botanic7arc/items/4b74e97d1a58a1443196)


# 参考文献
- [コンポーネントの state – React](https://ja.reactjs.org/docs/faq-state.html)
- [コンポーネントと props – React](https://ja.reactjs.org/docs/components-and-props.html)
- [GitHub - typescript-cheatsheets/react: Cheatsheets for experienced React developers getting started with TypeScript](https://github.com/typescript-cheatsheets/react#function-components)
- [Reactの基本を学ぼう～コンポーネントで動的な状態管理 (1/3)：CodeZine（コードジン）](https://codezine.jp/article/detail/11748)
- [今更聞けない JSX のコメントアウトの構文 - Qiita](https://qiita.com/naoiwata/items/c590667765143c41d87a)