世界一やさしいReact×TypeScriptを使ってAPIからデータを取得する方法

#### 背景

ReactでAPIからデータを取得する方法は、少し探せばたくさんヒットします。Axiosを使うのが定番ですね。
ところがTypeScript環境だと参考になる情報が急に少なくなります。

#### 検証した環境

* React v18.2.0
* Axios v1.3.4
* Windows 11
  Linuxでも同様にデータ取得できます。

#### React×TypeScriptでプロジェクトを構築する

* コマンドプロンプトもしくはPowerShellを開いて下記を実行する
  ```
  >npx create-react-app --template typescript myapp
  ```
* 動作することを確認する
  ```
  >cd myapp
  >npm start
  ```
* ブラウザが開いて"Learn React"と表示されれば成功です。

#### Axiosを用いたデータ取得を実装する

* やりたいこと
  GETメソッドで下記の郵便番号検索APIからデータを取得します
  https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060
* まずaxiosをインストールします
  ```
  >npm install axios
  ```
* src/App.tsxのファイルを書き換える
```Typescript:App.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';

function App() {
  axios.get("https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060")
    .then((results) => {
      console.log(results.data);
    })
    .catch((error) => {
      console.log('失敗');
      console.log(error.status);
    });
  return (
    <div className="App">
(変更なし。以下省略)
```
* F12キーを押してブラウザのデベロッパーツールのコンソールを見て郵便番号データを取得できていることを確認する。

### 取得したデータを画面に反映させる

さてここまででAPIからデータを取得できることがわかったのですがやはり画面上に表示させたいですよね。
「App.tsx」をこのように書き換えましょう。

```Typescript:App.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';

function App() {
  const { useState, useEffect } = React;
  const [message, getMessage] = useState("783-0060の都道府県は？");
  useEffect(() => {
    axios.get("https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060")
      .then((results) => {
        console.log(results.data);
        getMessage(results.data.results[0].address1);
      })
      .catch((error) => {
        console.log('失敗');
        console.log(error.status);
      });
  });
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        <p>{message}</p>
      </header>
    </div>
  );
}

export default App;
```
* address1には都道府県名が入ります。
  そこで「Learn React」の下に郵便番号「783-0060」に対応する都道府県である「高知県」と表示されれば成功です。
* 変数messageでAPIから取得したデータを保持しており、関数getMessageで変数messageのデータ更新を行っています。
* [Reactのフック機能](https://ja.reactjs.org/docs/hooks-intro.html)を使っています。useStateとuseEffectがキモですね。興味がある人は調べてください。
* [useAxios](https://github.com/kwhitejr/use-axios)を使うとフックを意識することなくAPIからデータ取得できるそうな。

#### 新しいクラスを作って画面に反映させる

Reactではコンポーネントごとに新しいクラスを作るのが基本です。
この方法でもやってみましょう。
* 新しくMyClass.tsxファイルを作成する
```Typescript:MyClass.tsx
import React from 'react';
import axios from 'axios';

export default class MyClass extends React.Component {
  state = {message: "999-6852の都道府県は？"}

  componentDidMount() {
     axios.get("https://zipcloud.ibsnet.co.jp/api/search?zipcode=9996852")
      .then(res => {
        const mes = res.data.results[0].address1;
        console.log(mes)
        this.setState({message: mes});
      })
  }

  render() {
    return (
      <h1>
        {this.state.message}
      </h1>
    )
  }
}
```
* index.tsxにMyClassを追加する
```Typescript: index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import MyClass from './MyClass'

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <App />
    <MyClass />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```
* 関数componentDidMount()とsetStateの組み合わせです。少し古いやり方のようです。
* 表示させてみましょう
![2023-03-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268595/0bc4d6f8-5b18-9402-5a78-2e5815a6c3f5.png)
* ウェブページの一番下に999-6852の都道府県である「山形県」と表示されれば成功です