Go(Gin)✖️React でAPI実装

# 記事作成理由
今回、GoとReactでアプリを作成する際にAPIの呼び出しに手こずったので、忘れないためにも書き残します（Viteは別）。
分からない人の参考になれば幸いです。

## 準備
### 環境
- Mac OS
- VSCode
- Go v1.19
- React v18.2.0

### インストール等
```
//プロジェクトフォルダ作成（今回はsample）
$ mkdir sample
$ cd sample
//backendフォルダ作成
$ mkdir backend
$ cd backend
// main.goファイル作成
$ touch main.go
// go.modファイル作成
$ go mod init sample
// Ginインストール
$ go get -u github.com/gin-gonic/gin
// 
$ cd ..
// Reactプロジェクト作成（Viteも可）
$ npx create-react-app frontend
//axiosインストール
cd frontend
npm install axios
// VSCode開く
$ code .
```

### ディレクトリ構造
```
sample
  ├── backend
  │     └── Go系
  └── frontend
        └── React系
```

## コード

今回はGo側でCORSの設定はしない
[参考サイト](https://nansystem.com/gin-get-post-json-form/)

``` Go:main.go
package main

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
)

type JsonRequest struct {
	Message string `json:"message"`
}

func main() {
	router := gin.Default()

	// Go -> React
	router.GET("/api", func(ctx *gin.Context) {
		ctx.JSON(http.StatusOK, gin.H{
			"message": "This message from Go api",
		})
	})

	// React -> Go
	router.POST("/api/message", func(ctx *gin.Context) {
		var jr JsonRequest
		if err := ctx.ShouldBindJSON(&jr); err != nil {
			fmt.Println("Error Occured")
		} else {
			fmt.Println(jr.Message)
		}
	})

	// http://localhost:8080
	router.Run()
}

```
<hr/>
index.htmlやApp.jsの必要のない記述、画像ファイル等は、事前に削除してください。

[参考サイト](https://www.freecodecamp.org/japanese/news/how-to-use-axios-with-react/)

``` React:App.js
import './App.css';
import {useEffect, useState} from'react';
import axios from 'axios';

function App() {
  const [data, setData] = useState();
  
  // Go -> React
  useEffect(() => {
    const getData = async () => {
      try{
        const res = await axios.get('/api');
        setData(res.data);
      }catch(e){
        console.log(e);
      }
    }
    getData();
  }, [])

  // React -> Go
  const createPost = () => {
    axios.post('/api/message', {message: 'This message from React'});
  }
  

  return (
    <div className="App">
      <h1>Hello, World</h1>
      <div>Recieved -&gt; {data ? data.message : 'No data'}</div>
      <br/><br/>
      <button onClick={createPost}>Create POST</button>
    </div>
  );
}

export default App;

```
ターミナルを二つ立ち上げ、GoとReactを実行する
![Screen Shot 2023-06-09 at 16.02.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039114/a53abbe2-0433-ee84-65f1-b6032e7d5e1d.png)
<hr/>

実行すると、Reactのポートが3000なのに対しGoのポートが8080のため、Requestを送っても見つからないというAxiosErrorが発生する。

![Screen Shot 2023-06-09 at 12.17.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039114/a11a2e2d-09f9-5329-a44c-355926d461ec.png)


回避するため（Go側のポートを通してあげるため）に、frontendフォルダ直下のpackage.jsonに`"proxy": "http://localhost:8080"`を追記(今回は開発者用の設定)
[参考サイト](https://create-react-app.dev/docs/proxying-api-requests-in-development/)
``` json:package.json
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "proxy": "http://localhost:8080",
}
```

Viteの場合、```vite.config.js```ファイルをに下記を追加
```react:vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server:{
    proxy: {
      "/api": {
        target: "http://localhost:8080",
        changeOrigin: true,
      }
    }
  }
})

```

<hr/>
再度実行すると、下記画面でGoからレスポンスを受け取っているのが確認できる

![Screen Shot 2023-06-09 at 16.08.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039114/ce2f14c8-8f92-ea30-8fc6-a46dc6e76cc8.png)

Create POSTボタンを押下すると、Reactで発行した値を受け取れているのが確認できる

![Screen Shot 2023-06-09 at 16.12.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039114/154d8b99-5267-934d-be83-41a76060240f.png)
<br/><br/>
**以上**