Next 基礎 Part 02 -- axios で API を叩けるようにする。No 'Access-Control-Allow-Origin' エラーの解決。
Tags: nextjs, japanese, cors
Published: 2023-03-01 15:45:06



## why

前回の記事で Next.ts プロジェクトをテンプレで作った。
今回は API を呼べるようにする。

Axios 入れて　useEffect で呼ぶだけでは叩けなかった。
6h ほどハマったので、解決策を記事にしておく。

---

## axios のインストール

```php
npm i axios
```

axios を使うことで　HTTP リクエストができる。

---

## UseEffect について

初回起動時に API を叩くように。

https://masa-engineer-blog.com/react-hook-useeffect/

第 2 引数がないと初回のみ動く
第 2 引数があると第 2 引数の更新時のみ動く

---

## axios.create で　GET リクエストをする

Home で

```ts
  const axiosInstance = axios.create({
    baseURL: "http://localhost:8080",
    headers: {
      'Content-Type': 'application/json',
    },
  })
```

- ベースの　URL 
- コンテンツタイプが JSON

ということを指定してインスタンスを作る

```ts
  const getHeardOn = async () => {
    console.log("getHeardOn");
    await axiosInstance
      .get(`/heard-on`)
      .then((response)=>{
        setHeardOn(()=> response.data)
      })
      .catch((e) =>{
        console.log(`Error: ${e}`);
      })
  }
```

次にインスタンスを使って
/heard-on に　GET リクエストをする。
/heard-one は person-api で作ったエンドポイント。

---

## useEffect で初回ロード時に呼び出す

```ts
  useEffect(() => {
    console.log("loaded");
    getHeardOn()
    console.log(heardOn);
    
  })
```

初回ロード時に getHeardOn を呼び出すようにする。

```ts
Access to XMLHttpRequest at 
'http://localhost:8080/heard-on' 
from origin 'http://localhost:3000' 
has been blocked by CORS policy: 

No 'Access-Control-Allow-Origin' header is present 
on the requested resource.
```

localhost 3000 からのリクエストが
CORS によって弾かれた。

Access-Control-Allow-Origin
というヘッダーがリクエストのリソースに存在しない

とエラーが出た。

## Access-Control-Allow-Origin をヘッダーに追加して送信に失敗

https://stackoverflow.com/questions/45975135/access-control-origin-header-error-using-axios

この記事を参考にして

```ts
  const axiosInstance = axios.create({
    baseURL: "http://localhost:8080",
    headers: {
      'Content-Type': 'application/json',
      "Access-Control-Allow-Origin": "*",
    },
  })
```

Access-Control-Allow-Origin: * 
で
アクセスを許可する元：全て
にしたヘッダーを作ってリクエストした。

```ts
Access to XMLHttpRequest 
at 
'http://localhost:8080/heard-on' 
from origin
'http://localhost:3000' 
has been blocked by CORS policy: 

Response to preflight request 
doesn't pass access control check: 

No 'Access-Control-Allow-Origin' header 
is present on the requested resource.
```

https://qiita.com/kurab/items/84573b3092c8db4ba750#preflight-request-%E3%81%AE-ok-status-%E3%82%92%E8%BF%94%E3%81%99

kurab さんのにている記事を見つけたが少し違う。

やはり 'Access-Control-Allow-Origin' がついてないと怒られている。

axios インスタンスにつけるだけではダメなようだ。

----

## next config の rewrite でローカルに送っている体にする

next.config.js

```ts
/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/(.*)',
        destination: 'http://localhost:8080',
      },
    ]
  },
};


module.exports = nextConfig
```

これで　baseURL なしで、
デフォルトの localhost 3000 に送るコードが
到着地の localhost8080 に書き換わって送信される。

index.tsx

```ts
  const axiosInstance = axios.create({
    // baseURL: "http://localhost:8080",
    headers: {
      'Content-Type': 'application/json',
    },
  })
```

なので　baseURL を外した。これで 8080 に送信できる。

実際に person-api と　person-web を動かすと


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e8ycn6n8nt2p3y6icele.png)

上記のレスポンスで

これで解決した。

---

## rewrite の詳細

https://nextjs-ja-translation-docs.vercel.app/docs/api-reference/next.config.js/rewrites

公式を見ると、
rewrite / source, destination は
proxy として mask するとある
/ へのリクエストを /about に変えて送るものだと解釈した。

なのでこの rewrite と proxy を使う。
localhost 3000 にリクエストさせるように見せる。
実際は localhost 8080 にリクエストさせる。

Next からは localhost 3000 の自分自身に送るように見える。
なので CORS エラーが出ない。

以上。