◆ Spring Bootで作成したAPIをReactからGETする

# ★ はじめに
Springの勉強と並行してNode.jsとReactの学習も進めているのですが、フロント側は苦手意識があるせいか進捗が悪いです。
例のごとく作業メモ兼勉強記録の記事になります。

# ★ やりたいこと
掲題ママ。
[◆ SpringBoot+gradle REST+JSON形式のAPIを呼び出してみる](https://qiita.com/Haru_3/items/319b626afcfe8131ad43)
で作成したAPIをフロント側でコールする処理の実装を行います。

ところで業務では基本サーバサイド、独自のフレームワークを使ったAPI開発をメインで行っています。バッチからAPIをコールする処理を実装した経験はあっても、フロント側、画面からAPIをコールする処理を実装をする経験はなかなかないので、いい勉強になりました。

# ★ API側（SpringBoot）
```java:RestApiController.java
package com.example.sample.app.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.example.sample.app.resource.BirthStone;

@RestController
@CrossOrigin(origins = "*") // ★変更点
@RequestMapping("api/sample")
public class RestApiController {
    
    @RequestMapping(value = "/getBirthStone", method = RequestMethod.GET)
    @ResponseBody
    public BirthStone getBirthStone() {
        BirthStone birthStone = new BirthStone("2月", "アメジスト", "紫");
        return birthStone;
    }
}
```
実際に画面から呼んだ際に、
**「クロスオリジン要求をブロックしました: 同一生成元ポリシーにより、【※APIのURL】 にあるリモートリソースの読み込みは拒否されます (理由: CORS ヘッダー ‘Access-Control-Allow-Origin’ が足りない)。[詳細]」**
なんてエラーメッセージがコンソールに出力されたのでなんじゃそりゃ、と思ったら**CORS**でエラーになっていたみたいです。
不勉強のためまずCORSという言葉を初めて知りました。
いまだに把握しきれていないので、後日勉強予定。余力があれば記事にしたいです。

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/CrossOrigin.html

`@CrossOrigin`アノテーションをつけることで、CORSを制御できるとのこと。
`origins`(Access-Control-Allow-Origin)は"*"（ワイルドカード）を設定。

ローカルで起動します。ポートはデフォルトの8080。

# ★ 画面側（React）
```
// プロジェクト作成
create-react-app call_api_sample
// プロジェクトに移動
cd  call_api_sample
// node-fetchのインストール
npm install --save node-fetch
// サーバ起動
npm start
```
プロジェクトを作成し、FetchAPIを使いたかったのでインストールしました。
サーバを起動します。ポートはデフォルトの3000。

```React:App.js
import React, { Component } from 'react';
import fetch from 'node-fetch';
import './App.css';

class App extends Component {
  constructor (props) {
    super(props)
    this.state = {
      month: '',
      name: '',
      color: ''
    }
  }
  componentWillMount () {
    const URL = 'http://localhost:8080/api/sample/getBirthStone'
    fetch(URL, {mode: 'cors'})
    .then(res => res.json())
    .then(json => {
      this.setState({
        month: json['month'],
        name: json['name'],
        color: json['color']
      })
    });
  }

  render() {
    return <div className='App'>
      month: {this.state.month} <br />
      name: {this.state.name} <br />
      color: {this.state.color} <br />
    </div>
  }
}

export default App;
```

別のjsファイル作ろうかと思いましたが簡単な疎通確認程度でしたので、App.jsを書き換えました。

`constructor`でmonth、name、colorの初期化（空）を行っています。

`componentWillMount`（コンポーネント作成前に実行される処理）でAPIを呼び出し、レスポンス値をmonth、name、colorに詰めています。
CORS対応するため、`mode`には'cors'を設定。

# ★ 実行結果
http://localhost:3000/
にアクセスすると...

![WS000006.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154016/38c0848c-6d90-04d5-9e62-cc11289b6da6.jpeg)

APIのレスポンス値が画面に表示されました。

# ★ 参考
本記事の執筆にあたり、以下書籍・記事を参考にさせていただきました。

[いまどきのJSプログラマーのための Node.jsとReactアプリケーション開発テクニック](http://www.socym.co.jp/book/1114)

[CORSまとめ](https://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34#)
[【JavaScript基礎】Fetch APIの基礎 - KDE BLOG](https://kde.hateblo.jp/entry/2018/10/22/010811)
[Node.jsでfetchを使えるようにする](https://morizyun.github.io/javascript/node-js-npm-library-node-fetch.html)
[お疲れさまXMLHttpRequest、こんにちはfetch](https://qiita.com/tomoyukilabs/items/9b464c53450acc0b9574)