React.jsでボタンをおしたら何かを表示するやつを試行錯誤しながらサンプルに追加するチュートリアル その２

## これはなに？

[React.jsでボタンをおしたら何かを表示するやつを試行錯誤しながらサンプルに追加するチュートリアル](https://qiita.com/567000/items/f6268fa406b17bb3f884) のその２です。

前回までで、ボタンをおしたら外部のAPIをたたいて結果を表示するようなサンプルができあがっています。
今度は、前回説明を省略した `this` や `state` について説明しつつサンプルを変えていきます。

**前回から、不要なHTMLの削除や、テキストやコメントを変えているのでご注意ください**

下記のコードで`App.js`を書き換えてから`npm start`でサーバを動かして、ブラウザで確認してみましょう。
前回同様の動きになったら次に行ってみましょう。

```JavaScript:src/App.js
import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <a onClick={this.handleClick}>住所を表示</a>

          <p>{this.state.tenki}</p>

        </header>
      </div>
    );
  }
  handleClick() {
    fetch('https://api.zipaddress.net/?zipcode=1000005', {
      mode: 'cors'
    })
    .then(res => {
      return res.json();
    })
    .then(json => {
      this.setState({tenki:json.data.fullAddress});
    })
  }

  constructor(props) {
    super(props);
    this.state = { tenki : "まだ住所をとってません" };
    this.handleClick = this.handleClick.bind(this);
  }
}

export default App;
```

## 状態遷移とかデータの受け渡しとかをしてみる

さて、前回に加えて、もう少しReact.jsっぽいことをチュートリアル的にやってみます。

**「郵便番号」の入力ができるようにして、「住所を表示」を押すと、該当の住所が表示される**

前回がボタンを押すだけだったのに対して、今回は入力のフォームもつけてみました。

## 「郵便番号」の入力テキストボックスをつける！

```JavaScript:src/App.js
import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          {/* ***** テキストボックス ***** */}
          <p>郵便番号をいれてください</p>
          <p><input type="text" value={this.state.zip_code} /></p>
          {/* ***** ここまで ***** */}

          <a onClick={this.handleClick}>住所を表示</a>

          <p>{this.state.tenki}</p>

        </header>
      </div>
    );
  }
  handleClick() {
    // クエリにinputされたzip_codeを使う
    fetch('https://api.zipaddress.net/?zipcode=' + this.state.zip_code, {
      mode: 'cors'
    })
    .then(res => {
      return res.json();
    })
    .then(json => {
      this.setState({tenki:json.data.fullAddress});
    })
  }

  constructor(props) {
    super(props);
    // **** 住所を扱うために zip_code という値をstateに追加
    this.state = { tenki : "まだ住所をとってません", zip_code : '1000005' };
    this.handleClick = this.handleClick.bind(this);
  }
}

export default App;
```

追加したところ少し詳しく見てみます。
まず`<input>`タグを追加しています。これは単なるHTMLなので問題ないですね。`input`の`value` には `{this.state.zip_code}` という変数を指定しているところだけ注意です。

`value`に使った`this.state.zip_code`という変数ですが、勝手に使うわけにもいかないので、コンストラクタのところで、`this.state =...` に `zip_code` の初期値を追加してあります。

そして、最後に、この `zip_code` の値がAPIのクエリに使われるようにするために、`fetch`のクエリ（URL）書き換えています。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/33095/e2505cdf-7eaa-87fd-12d9-15c366ab09b6.png)

ということで実際起動してクリックしてみるとこんな感じになります。

## あれ値が書き換わらないぞ？

やってみればわかりますが、このままだと`input`のところを書き換えようとしても値が書き換わりません。

なぜかというと、`value`の値が`this.state.zip_code`になっているからです。

どれだけテキストボックス上で値を書き換えようとしても、`value`の値は`this.state.zip_code`になり続けるので、変わることができないのです。 `input`には、初期値で入力された`this.state.zip_code`が表示され続けてしまいます。

ということで、どうするかというと、要は `this.state.zip_code` を変えてあげればいいのです。

## 値が変わるようにする

```JavaScrpt
    :
          <p><input type="text" value={this.state.zip_code} onChange={(e) => this.setState({zip_code: e.target.value})} /></p>
    :
```

`input`に`onChange={(e) => this.setState({zip_code: e.target.value})}`を追加します。

つまり何をしているかというと、`input`の値がかわる`onChange`イベントを使って、値が変わるたびに`setState`を呼び出して値を書き換えていくのです。

これで、無事に値を書き換えることが出来ます。

実際に動かして、郵便番号を変えて住所をとってきてみましょう。

> エラー処理してないので存在しない番号をいれてもエラーもなにもでてきません^^

## ちょっとだけ色気を出して

値によって処理を変えます。

まあ、たいしたことはしません。 住所が 東京 だったときだけ色を変えるというだけです。

```JavaScript:src/App.js
import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <p>郵便番号をいれてください</p>
          <p><input type="text" value={this.state.zip_code} onChange={(e) => this.setState({zip_code: e.target.value})} /></p>

          <a onClick={this.handleClick}>住所を表示</a>

          {/* ***** p に style を指定 ***** */}
          <p style={this.state.address_style}>{this.state.tenki}</p>

        </header>
      </div>
    );
  }
  handleClick() {
    fetch('https://api.zipaddress.net/?zipcode=' + this.state.zip_code, {
      mode: 'cors'
    })
    .then(res => {
      return res.json();
    })
    .then(json => {
      // 東京という文字がはいっているかどうかで style を変更
      if ( json.data.fullAddress.indexOf('東京') !== -1 ){
        this.setState({address_style:{color:"red"}})
      }
      else {
        this.setState({address_style:{color:"white"}})
      }
      this.setState({tenki:json.data.fullAddress});
    })
  }

  constructor(props) {
    super(props);
    this.state = { tenki : "まだ住所をとってません", zip_code : '1000005', address_style : {} };
    this.handleClick = this.handleClick.bind(this);
  }
}

export default App;
```

まあ、こんな感じです。

こういうところ１つとってもReact（JSX）はちょっとずつクセがありますね。
`style` って普通は`文字列`で指定する属性ですけど、JSXでは `{}` になってますよね、こういう微妙な差異がなかなか慣れるまでは難しいところです。