State を使った React コンポーネント（React基礎講座6）

# はじめに

今回は、State を使った React コンポーネントについて書きたいと思います。

# シリーズ

本記事はReact基礎講座のための連載になっています。気になる方のために、前の章は以下です。

[これまでの復習、コンポーネントを別ファイルにしてコールする（React基礎講座5） \- Qiita](https://qiita.com/ryosuketter/items/957135d0334d7ff070d3)

最初の記事は、以下です。

[Reactを使ってJSXの内容をレンダリングする（create\-react\-app）（React基礎講座1） \- Qiita](https://qiita.com/ryosuketter/items/dbac89f398787a1a73d4)

# State とは

同じのコンポーネントだけど、コンポーネントが持つ内部の `state` の違いによって見た目や振る舞いが変わって行きます。

人間で例える、年齢を `state` としてもいいでしょう。また、車で例えると、社名やナンバープレートを `state` としてもいいでしょう（それが最適かはわかりませんが）。

## React コンポーネント が State を持つと何がいいのか？

コンポーネント中にあるテキストや、cssのクラスなどを動的に変化させることができます。

# ES2015(ES6) における クラス構文

React の `state` を持った Component は基本、クラス構文と同じような書き方なので、まずは、ES2015(ES6) における クラス構文を学んで理解して行きましょう。

まずは、JSにおける最小限のクラスを書いて行きましょう。

様々な車のオブジェクトを生成する `Car` クラスを生成し、インスタンス（オブジェクト）を作ってコンソールで表示させてみましょう。

```js
// jsのクラスの基本的な定義
class Car {
  constructor() {}
}

// インスタンス（オブジェクト）の生成
const Prius = new Car();

// コンソールの確認
console.log(Prius);
```

コンソールは、以下のように表示されます。

![スクリーンショット 2019-08-10 08.02.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/d7966187-8596-40b2-0a8d-3574f558df57.png)

## 引数を受け取れるようにしましょう

`Car` クラス に引数として、名前とプレート番号を受け取れるようにします。クラス内では、constructorに定義します。
イオンスタンスを生成する際に、二つの引数を定義します。

実際に書いてみます。

```js
class Car {
  constructor(name, number) {
    this.name = name;
    this.number = number;
  }
}

const Prius = new Car("prius", "品川あ00-00");
console.log(Prius);
```

すると、コンソールではオブジェクトの中に定義された2つの引数に渡した値が表示されています。

![スクリーンショット 2019-08-11 22.36.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/42ee028c-ed71-e1a6-11ca-8796abb2eea3.png)

クラスなので別のインスタンス（オブジェクト）というか、車（`カローラ`）も定義してみましょう。

```js
class Car {
  constructor(name, number) {
    this.name = name;
    this.number = number;
  }
}

const Prius = new Car("prius", "品川あ00-00");
console.log(Prius);

const Corolla = new Car("corolla", "品川あ00-00");
console.log(Corolla);
```

すると、２つ、インスタンス（オブジェクト）ができました。

![スクリーンショット 2019-08-11 22.46.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/0f80551b-2cc0-2c2e-2b26-0635c33991e0.png)

1つのクラス（テンプレート）から、複数のインスタンス（オブジェクト）ができるところが、クラスの素敵なポイントですね。

では、クラスに関数を持たせてみましょう。（JSでは、クラスが持つ関数をファンクションやメソッドと言います。）

関数の内容は、定義されたデータ（今回なら、名前とプレート番号）を表示する内容にします。では、関数（名前 `callMySpec`）を作成し、実際にコールしてみましょう。

```js
class Car {
  constructor(name, number) {
    this.name = name;
    this.number = number;
  }

  // 関数（名前 `callMySpec`）を作成
  callMySpec() {
    console.log(this.name, this.number);
  }
}

const Prius = new Car("prius", "品川あ00-00");
console.log(Prius);
// 実際にコールしてみました
Prius.callMySpec();

const Corolla = new Car("corolla", "品川あ00-00");
console.log(Corolla);
// 実際にコールしてみました
Corolla.callMySpec();
```

すると、関数も動いていることがコンソールからわかります。
オブジェクトにドットとつけて、`メソッド名()`をつけてクラスメソッドをコールするシンタックスが分かりました。

![スクリーンショット 2019-08-11 23.03.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e4198b04-edbf-9ef9-12bd-f2d567e03596.png)

# React における クラスコンポーネント の書き方

ES2015(ES6)におけるクラスシンタックスが分かったので、今度は、ReactのStateを持ったクラスで書くコンポーネントを実装して行きます。

```react
import React from "react";
import { render } from "react-dom";

class Car extends React.Component {
  constructor(props) {
    super(props);

  }

  render() {
    return <h1>test</h1>
  }
}

render(<Car />, document.getElementById("root"));
```

重要なのは `extends React.Component` の部分ですね。

`React.Component`の機能を継承（`extend`）した`Car`クラスである、ということが言えます。

これは、ただのJSのクラスではなく、この後に説明する`state`や`props`（`React.Component`の機能）を利用できる`Car`クラスと言えます。

そして、constructor内で`props`を受け取って`super(props)`で実行する。という記述は定型文として覚えてください。

`super`は、`extend`した内容を引き継いでいます。書き方（↓）

```
...
constructor(props) {
    super()
  }
...
```

は定型文として覚えてください。

そして、`React`における クラスコンポーネントでは、`render()`というメソッドが必要になります。これは、どんなコンポーネントを実際に返すかというコンテンツ部分になります。

これらを、まとめて、クラスコンポーネントではなく、 `React.Component`で書くと

```react
import React from "react";
import {render} from "react-dom";

class Car extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return <h1>{this.props.name}</h1>
  }
}

render(<Car name='corolla' />,document.getElementById("root"));
```

これは、nameの内容を`props`として渡しています。

すると、viewには`corolla`と表示されます。

`name`を`state`として定義するには、以下のように

```react
import React from "react";
import { render } from "react-dom";

class Car extends React.Component {
  constructor(props) {
    super(props);
    // stateの定義はオブジェクト記法で定義する
    this.state = { name: "corolla" };
  }

  render() {
    return <h1>{this.state.name}</h1>;
  }
}

render(<Car />, document.getElementById("root"));
```

これも同じく、viewには`corolla`と表示されます。

# クリックした時に state（状態） を変更する処理

今度は、クリックした時に `<h1>`にある車の車種名のstate（状態） をメーカー名に変更する処理を書いていきます。

具体的の処理の記述は

- 新たに`state`（`maker`）とその値（`toyota`）を加える
- `h1`タグの下に`button`タグを設置して、クリックした際に発火するメソッドを指定する
- メソッドを作成する
    - メソッドの内容は「クリックしたら makerのstateの値に変更する」
    - その時に`state`を更新するメソッドは`setState`を利用してください
    - メソッド名は `showMakerName` （this.の影響範囲もあるので、アロー関数で実装する）
- 上に書いたReactの記述から機能を足していきます

## 記述内容（正解）

```react:index.js
import React from "react";
import { render } from "react-dom";

class Car extends React.Component {
  constructor(props) {
    super(props);
    // stateの定義はオブジェクト記法で定義する
    // 新たに state （ maker ）とその値（ toyota ）を加える
    this.state = { name: "corolla", maker: "toyota" };
  }

  // h1タグの下に button タグを設置して、クリックした際に発火するメソッドを指定する
  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
        <button onClick={this.showMakerName}>add</button>
      </div>
    );
  }

  // メソッドを作成する
  showMakerName = () => {
    this.setState({ name: this.state.maker });
  };
}

render(<Car />, document.getElementById("root"));
```

すると、ボタンタグをクリックしたら、`state`（`maker`）の値（`toyota`）に変更されている事がわかります。

![11a1e443ab0bba596b51dc0740e3ea09.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/1ee2fc41-59ef-5ccd-5c00-f959bc81f1f6.gif)

以上です。参考にしてみてください。

# 参考

- 改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで | 山田 祥寛